A一条线,B一条线,平行遥相望,不知何时相交。
C一个线程,D一个线程,齐头并进,最好不相聚。
(图片选自百度)
做过开发的都知道,为了用户体验好,耗时长的case我们都放到子线程去做,譬如:下载,数据访问,网络访问等。
在IOS中,多线程有三种技术,NSThread,NSOperation,GCD,其中NSThread和大家平时各语言中使用的Thread类似。
汇总:
- NSThread:比其他两个要轻量级,创建一个线程十分方便,但需要我们自己维护生命周期和线程同步,所以不建议用它来实现多线程。建议用[NSThread currentThread]来跟踪任务所在线程十分方便,且适用于这三种技术。
- NSOperation/NSOperationQueue:由GCD实现的一套Objective-C的API,面向对象的多线程技术,但它提供了一些在GCD中不容易实现的特性,如:限制最大并发数量,设置各操作间的依赖关系。操作队列比GCD性能要略低,但可以忽略不计,在并发编程中,推荐使用NSOperation/NSOperationQueue
- GCD:是基于C语言的底层API,我们不用去关心它的内部实现。它使用Block定义任务,使用起来十分灵活,提供了更多的控制能力以及NSOperationQueue中所不能使用的底层函数。抽象度最高,使用最简单,苹果最推荐使用的多线程编程技术(为多核的并行运算提出的解决方案)。
这一篇,我们先介绍NSThread的使用:
NSThread的方法介绍:
- 获取当前运行的线程:
[NSThread currentThread];
- 自动创建一个新的线程执行target对象的func方法,参数通过argument对象传入(只能传递一个参数,如果有多个请使用对象封装哦):
[NSThread detachNewThreadSelector:@selector(func) toTarget:target withObject:argument];
- 判断是否为多线程:
[NSThread isMultiThreaded];
- 阻塞当前线程到某个时间,date为这个时间点NSDate类型
[NSThread sleepUntilDate:date];
- 阻塞当前线程多长时间,time单位为秒(NSTimeInterval)
[NSThread sleepForTimeInterval:time];
- 强制终止线程:
写在线程内部,退出当前线程:
[NSThread exit];
- 调度优先级:
调度优先级的取值范围是0.0 ~ 1.0,默认0.5,值越大,优先级越高
自己开发时,不要修改优先级,否则一旦出现“优先级反转”会非常麻烦
thread. threadPriority = 1;
- 判断当前线程是不是主线程:
[NSThread isMainThread];
- 判断thread是不是主线程:
thread.isMainThread;//readonly
- 获取主线程:
[NSThread mainThread];
- 线程初期化:
[[NSThread alloc] init];
- 初期化线程,启动后会调用target的func方法,参数通过argument对象传入(只能传递一个参数,如果有多个请使用对象封装):
与detachNewThreadSelector不同的是,需要自己调用start方法启动。
NSThread *thread = [[NSThread alloc] initWithTarget:target selector:@selector(func) object:argument];
[thread start];
- 判断线程是否在执行:
thread.isExecuting;//(readonly)
- 判断线程是否执行完毕:
isFinished;//(readonly)
- 判断线程是否已被取消:
isCancelled;//(readonly)
- 开始运行线程:
[thread start];
- 取消执行该线程:
[thread cancel];
另外还有一些关于线程的方法,属于NSObject:
- 主线程执行某操作:(在子线程完成后更新UI时常用)
注:子线程任务完成后,需要更新页面,子线程本身是不能操作UI的,所以需要调度到主线程中执行更新UI的方法:
aSelector:在主线程要执行的方法;
arg:方法需要的参数
wait:YES指定,同步阻塞,当前线程被阻塞,直到主线程将我们制定的代码块执行完才进行当前线程后面代码;
NO指定,异步非阻塞,当前线程和主线程异步执行。
[self performSelectorOnMainThread:@selector(aSelector) withObject:arg waitUntilDone:wait];
- 子线程执行某操作:
参数与performSelectorOnMainThread:withObject:waitUntilDone:方法一致,除了多了个onThread:,其参数是你要运行aSelector方法的自定义线程。
NSThread *thr = [[NSThread alloc] init];
[self performSelector:@selector(aSelector) onThread:thr withObject:arg waitUntilDone:wait];
- 后台执行某操作:
[self performSelectorInBackground:@selector(aSelector) withObject:arg];
以上方法的arg参数,当aSelector方法没有参数的时候,arg设为nil即可。
NSThread的detachNewThreadSelector:toTarget:withObject:方法和NSObject的perform开头的线程方法都是执行完该行代码后立即执行指定线程操作。NSThread的init开头的方法创建的线程需要自己手动调用start方法后才执行,当然,并不是说后者不好哦,后者可以设置好线程的属性后再执行。各有各的好处,根据自己需要即可。