多线程编程-NSThread

来源:互联网 发布:java文件上传中文乱码 编辑:程序博客网 时间:2024/06/05 00:39

多线程编程-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、程序设计更加复杂:比如线程之间的通信、多线程的数据共享

0 0
原创粉丝点击