多线程编程-NSThread

多线程编程-NSThread

每个iOS应用程序都有个专门用来更新显示UI界面、处理用户的触摸事件的主线程,因此不能将其他太耗时的操作放在主线程中执行,不然会造成主线程堵塞(出现卡机现象),带来极坏的用户体验。一般的解决方案就是将那些耗时的操作放到另外一个线程中去执行,多线程编程是防止主线程堵塞,增加运行效率的最佳方法
iOS支持多个层次的多线程编程,层次越高的抽象程度越高,使用也越方便,也是苹果最推荐使用的方法。下面根据抽象层次从低到高依次列出iOS所支持的多线程编程方法:

  1. Thread :是三种方法里面相对轻量级的,但需要管理线程的生命周期、同步、加锁问题,这会导致一定的性能开销
  2. Cocoa Operations:是基于OC实现的,NSOperation以面向对象的方式封装了需要执行的操作,不必关心线程管理、同步等问题。NSOperation是一个抽象基类,iOS提供了两种默认实现:NSInvocationOperation和NSBlockOperation,当然也可以自定义NSOperation
  3. Grand Central Dispatch(简称GCD,iOS4才开始支持):提供了一些新特性、运行库来支持多核并行编程,它的关注点更高:如何在多个cpu上提升效率

多线程的原理
同一时间,CPU只能处理1条线程,只有1条线程在工作(执行)
多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换)
如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象
这篇文章简单介绍了第一种多线程编程的方式,主要是利用NSThread这个类,一个NSThread实例代表着一条线程

一、NSthread的初始化

  1. 动态方法
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument 
    NSThread * thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(doAction) object:nil];
    //线程名
    thread1.name = @"thread1";
    //线程优先级,0 ~ 1
    thread1.threadPriority = 1.0;
    //开启线程
    [thread1 start];

参数解析:
selector :线程执行的方法,这个selector最多只能接收一个参数
target :selector消息发送的对象
argument : 传给selector的唯一参数,也可以是nil

  1. 静态方法
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
//通过类方法创建线程,不用显示的开启start
    [NSThread detachNewThreadSelector:@selector(doAction) toTarget:self withObject:nil];
  1. 隐式创建线程的方法:
    //隐式创建多线程
    [self performSelectorInBackground:@selector(doAction:) withObject:@"CYY"];

获取线程

    //获取当前线程
    NSThread *current = [NSThread currentThread];
    //获取主线程
    NSString *main = [NSThread mainThread];

可以在子线程获取主线程
NSLog(@"mainThread - %@",[NSThread mainThread]);

暂停当前线程

        //阻塞状态
        [NSThread sleepForTimeInterval:2];
        [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];

强制停止线程
[NSThread exit];
注意:一旦线程停止(死亡)了,就不能再次开启任务

线程间通信

主线程执行操作

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

在指定线程上执行操作

   [self performSelector:@selector(changeMainThread:) onThread:[NSThread mainThread] withObject:image waitUntilDone:YES];

在当前线程执行操作

   [self performSelector:@selector(setImage:) withObject:nil]

waitUntilDone:是什么意思?
YES:等待loadImage:这个方法执行完毕之后,再执行当前线程后续的操作
NO:不等待loadImage:这个方法执行完毕,就执行当前线程后续的操作

实例:卖票问题
有两个线程,两个线程之间不能同时进行,需要用到互斥锁

- (void)viewDidLoad {
    [super viewDidLoad];

    self.tickets = 20;

    NSThread * thread1 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
//    thread1.name = @"computer";

    [thread1 start];


    NSThread * thread2 = [[NSThread alloc] initWithTarget:self selector:@selector(saleTicket) object:nil];
//    thread2.name = @"phone";

    [thread2 start];
}

- (void)saleTicket {

    while (1) {

   //互斥锁
   @synchronized(self) {

       [NSThread sleepForTimeInterval:2];

       if (self.tickets > 0) {

           NSLog(@"%@ 还有余票 %@ 张",[NSThread currentThread],@(self.tickets));

           self.tickets -- ;

       } else {

           NSLog(@"票卖完了");

           break;
       }   
   }        
}    
}

NSThread优缺点

1、优点:NSThread比其他两种多线程方案较轻量级,更直观地控制线程对象
2、缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销

多线程的优缺点

一、多线程的优点
1、能适当提高程序的执行效率
2、能适当提高资源利用率(CPU、内存利用率)

二、多线程的缺点
1、开启线程需要占用一定的内存空间(主线程:1M,其他线程512kb),如果开启大量的线程,会占用大量的内存空间,降低程序的性能
2、线程越多,CPU在调度线程上的开销就越大
3、程序设计更加复杂:比如线程之间的通信、多线程的数据共享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值