• iOS学习笔记4线程 smallelephant_A


    一,创建线程

    主线程

        NSThread *current = [NSThread currentThread];

     或

        NSThread *main = [NSThread mainThread];

    子线程(三种方法)

        NSThread *thread= [[NSThread alloc]initWithTarget:self selector:@selector(run:) object:@"线程A"];

        NSThread *thread3 = [NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:@"创建完直接启动"];

        NSThread *thread3 = [self performSelectorInBackground:@selector(run:) withObject:@"隐式创建"];

    二,线程安全隐患

    以售票为例

    #import "ViewController.h"

    @interface ViewController ()

    @property (nonatomic,strong)NSThread *thread1;

    @property (nonatomic,strong)NSThread *thread2;

    @property (nonatomic,strong)NSThread *thread3;

    @property (nonatomic,assign)int leftTicketCount;

    @end

    @implementation ViewController

    - (void)viewDidLoad {

        [super viewDidLoad];

        

    //    默认有10张票

        

        self.leftTicketCount = 10;

        

        

        self.thread1 = [[NSThread alloc]initWithTarget:self selector:@selector(sellTicket) object:nil];

        self.thread1.name = @"售票员1";

        

        self.thread2 = [[NSThread alloc]initWithTarget:self selector:@selector(sellTicket) object:nil];

        self.thread2.name = @"售票员2";

        

        self.thread3 = [[NSThread alloc]initWithTarget:self selector:@selector(sellTicket) object:nil];

        self.thread3.name = @"售票员3";

        

        // Do any additional setup after loading the view, typically from a nib.

    }

    -(void)sellTicket

    {

        while (1) {

            int count = self.leftTicketCount;

            if (count>0) {

                [NSThread sleepForTimeInterval:0.2];

                self.leftTicketCount = count-1;

                

                NSThread *current = [NSThread currentThread];

                NSLog(@"%@--卖了一张票,还剩%d张票",current,self.leftTicketCount);

                

            }else{

            

                [NSThread exit];

            

            }

        }

    }

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

    {

        [self.thread1 start];

            [self.thread2 start];

        [self.thread3 start];

    }

    - (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

    }

    怎样解决 多个线程调用同一个对象

    用互斥锁 如下

    -(void)sellTicket

    {

        while (1) {

            

            

            @synchronized(self) {

                int count = self.leftTicketCount;

                if (count>0) {

                    [NSThread sleepForTimeInterval:0.2];

                    self.leftTicketCount = count-1;

                    

                    NSThread *current = [NSThread currentThread];

                    NSLog(@"%@--卖了一张票,还剩%d张票",current,self.leftTicketCount);

                    

                }else{

                    

                    [NSThread exit];

                    

                }

            }

            }

            

    }

    互斥锁的优缺点

    优点:能有效防止因多线程抢夺资源造成的数据安全问题

    缺点:需要消耗大量的CPU资源

     

    互斥锁的使用前提:多条线程抢夺同一块资源 

    相关专业术语:线程同步,多条线程按顺序地执行任务

    互斥锁,就是使用了线程同步技术

     

     

    三,原子性与非原子性

     

    OC在定义属性时有nonatomic和atomic两种选择

    atomic:原子属性,为setter方法加锁(默认就是atomic)

    nonatomic:非原子属性,不会为setter方法加锁

     

    atomic加锁原理

    @property (assign, atomic) int age;

    - (void)setAge:(int)age

    @synchronized(self) { 
    _age = age;
    }
    }

    原子和非原子属性的选择

    nonatomic和atomic对比

    atomic:线程安全,需要消耗大量的资源

    nonatomic:非线程安全,适合内存小的移动设备

     

    四,线程之间的通信

     

    线程之间需要用到通信,比如 下载一个图片,线程a需要等到线程b下载好之后再显示出来

    以下是例子

    //  ViewController.m

    //  线程间的通信

    //

    //  Created by 谢谦 on 16/2/16.

    //  Copyright © 2016年 杜苏南. All rights reserved.

    //

    #import "ViewController.h"

    @interface ViewController ()

    @property (nonatomic,weak)IBOutlet UIImageView *iconView;

    @end

    @implementation ViewController

    - (void)viewDidLoad {

        [super viewDidLoad];

        // Do any additional setup after loading the view, typically from a nib.

    }

    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event

    {

        [self performSelectorInBackground:@selector(download) withObject:nil];

    }

    -(void)download

    {

        NSURL *url = [NSURL URLWithString:@"fdsf"];

        NSData *data = [NSData dataWithContentsOfFile:url];

        

        

        UIImage *image= [UIImage imageWithData:data];

        

        [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];

        

    }

    -(void)settingImage:(UIImage *)image

    {

        self.iconView.image = image;

    }

    - (void)didReceiveMemoryWarning {

        [super didReceiveMemoryWarning];

        // Dispose of any resources that can be recreated.

    }

    @end

    对于   

        [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];

     有另外两种方法

        [self.iconView performSelector:@selector(settingImage:) onThread:[NSThread mainThread] withObject:image waitUntilDone:NO ];

        [self.iconView performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];

  • 相关阅读:
    Flowable学习笔记(二、BPMN 2.0-基础 )
    Flowable学习笔记(一、入门)
    只有程序员才懂的幽默
    Navicat自动备份数据库
    两个原因导致Spring @Autowired注入的组件为空
    设计模式—— 十二 :代理模式
    设计模式—— 十 一:建造者模式
    SpringBoot学习笔记(十一:使用MongoDB存储文件 )
    Swagger API文档集中化注册管理
    Spring Boot2从入门到实战:集成AOPLog来记录接口访问日志
  • 原文地址:https://www.cnblogs.com/adodo/p/5193294.html
Copyright © 2020-2023  润新知