iOS-多线程-NSThread

一、什么是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都做了什么:

start内部实现

通过上图,我们可以看出会创建一个pthread,然后执行mian方法,main方法内部调用了[target performSelector:selector];执行我们指定的任务,最后调用[NSTread exit];关闭线程退出。

推荐阅读更多精彩内容