一、什么是NSThread
NSThread是基于线程使用,轻量级的多线程编程方法(相对GCD和NSOperation),一个NSThread对象代表一个线程,需要手动管理线程的生命周期,处理线程同步等问题。
二、NSThread方法介绍
1. 动态创建
NSThread * newThread = [[NSThread alloc]initWithTarget:self selector:@selector(threadRun) object:nil];
动态方法返回一个新的thread对象,需要调用start方法来启动线程
2. 静态创建
[NSThread detachNewThreadSelector:@selector(threadRun) toTarget:self withObject:nil];
由于静态方法没有返回值,如果需要获取新创建的thread,需要在selector中调用获取当前线程的方法
3. 线程开启
[newThread start];
4. 线程暂停
[NSThread sleepForTimeInterval:1.0]; (以暂停一秒为例)
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
NSThread的暂停会有阻塞当前线程的效果
5. 线程取消
[newThread cancel];
取消线程并不会马上停止并退出线程,仅仅只作(线程是否需要退出)状态记录.
6. 线程停止
[NSThread exit];
停止方法会立即终止除主线程以外所有线程(无论是否在执行任务)并退出,需要在掌控所有线程状态的情况下调用此方法,否则可能会导致内存问题。
7. 获取当前线程
[NSThread currentThread];
8. 获取主线程
[NSThread mainThread];
9. 线程优先级设置
iOS8以前使用
[NSThread setThreadPriority:1.0];
这个方法的优先级的数值设置让人困惑,因为你不知道你应该设置多大的值是比较合适的,因此在iOS8之后,threadPriority添加了一句注释:To be deprecated; use qualityOfService below
意思就是iOS8以后推荐使用qualityOfService属性,通过量化的优先级枚举值来设置
qualityOfService的枚举值如下:
NSQualityOfServiceUserInteractive:最高优先级,用于用户交互事件
NSQualityOfServiceUserInitiated:次高优先级,用于用户需要马上执行的事件
NSQualityOfServiceDefault:默认优先级,主线程和没有设置优先级的线程都默认为这个优先级
NSQualityOfServiceUtility:普通优先级,用于普通任务
NSQualityOfServiceBackground:最低优先级,用于不重要的任务
比如给线程设置次高优先级:
[newThread setQualityOfService:NSQualityOfServiceUserInitiated];
三、线程间通信
常用的有三种:
1、指定当前线程执行操作
[self performSelector:@selector(threadRun)];
[self performSelector:@selector(threadRun) withObject:nil];
[self performSelector:@selector(threadRun) withObject:nil afterDelay:2.0];
2、(在其他线程中)指定主线程执行操作
[self performSelectorOnMainThread:@selector(threadRun) withObject:nil waitUntilDone:YES];
注意:更新UI要在主线程中进行
3、(在主线程中)指定其他线程执行操作
[self performSelector:@selector(threadRun) onThread:newThread withObject:nil waitUntilDone:YES]; //这里指定为某个线程
[self performSelectorInBackground:@selector(threadRun) withObject:nil];//这里指定为后台线程
四、线程同步
线程和其他线程可能会共享一些资源,当多个线程同时读写同一份共享资源的时候,可能会引起冲突。线程同步是指是指在一定的时间内只允许某一个线程访问某个资源
iOS实现线程加锁有NSLock和@synchronized两种方式
五、持久线程
我们会发现通过NSThread指定的线程在执行完任务就退出了,如何创建一个持久线程呢。
答案就是在线程内部运行一个持续运行的runloop:
NSRunLoop * runLoop1 = [NSRunLoop currentRunLoop];
[runLoop1 runUntilDate:[NSDate date]]; //一直运行
六、start内部到底执行了什么
NSThread需要[newThread start];
去开启,我们来看看start都做了什么:
通过上图,我们可以看出会创建一个pthread,然后执行mian方法,main方法内部调用了
[target performSelector:selector];
执行我们指定的任务,最后调用[NSTread exit];
关闭线程退出。