iOS中的多线程
现存的iOS多线程解决方案
现在在iOS中要实现多线程有如下四种方法。
Pthreads
NSThread
GCD
NSOperation & NSOperationQueue
Pthreads
这个基本没人用,大家可以静静地把他忽略。
NSThread
NSTread 一般也没什么人用,不过你需要知道的是他有俩个比较方便查看当前线程,和主线程的类方法。
//查看当前线程
[NSThread currentThread];
//查看主线程
[NSThread mainThread];
GCD
全称:Grand Central Dispatch. 一听就知道是屌炸天的东西了,我的最爱。好了废话不多说,聊聊他的使用吧。
概念
在GCD中有俩概念性的东西,一个叫queue(队列),sync or async(同步任务 和 异步任务)。也就是,我们准备好一系列的任务(sync or async),然后把这些任务丢到队列(queue)里。然后队列会根据FIFO的原则去取。
异步任务就是不会阻塞当前线程的任务,也就是要新开线程的任务。而同步任务就是 在当前线程,既你要等block里的任务完成,当前这个线程才能继续下去的意思。-
实际操作(讲那么多概念的东西好晕)
创建同步任务:就是对阻塞当前线程的任务(也就是不开线程了)//这里的queue可以是主线程(dispatch_get_main_queue()), //也可以是其他线程..... //不过要注意的是无论queue时什么,都会阻塞当前线程,知道block结束 dispatch_sync(queue, ^{ //code here NSLog(@"%@", [NSThread currentThread]); });
创建异步任务:就是不阻塞当前线程(也就是会另开一个线程),经常使用。
//如果这里的queue是主队列,那么就是去主线程。一般是刷新UI之类的 //如果这里的queue事全局队列,那么就是开异步线程加载数据 //全局队列dispatch_get_global_queue(优先级, 0) dispatch_async(queue, ^{ //code here NSLog(@"%@", [NSThread currentThread]); });
一般加载数据在异步线程,然后记载好数据要刷新UI的时候会到主线程。如下
dispatch_async(dispatch_get_global_queue(优先级, 0),^{ 加载数据; array = 加载好的数据。 dispatch_async(dispatch_get_main_queue(), ^{ 刷新UI; }); })
GCD还有一些东西,我们等会儿再扯。
NSOperation & NSOperationQueue
这个我个人用的很少,只有在处理线程资源依赖的时候用。来看看怎么用吧。
既然同步异步什么的我们完全可以借助GCD屌炸天实现,那么我们就看看NSOperation上比较有特色的东西吧。
添加依赖
/1.任务一:下载图片
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];
//2.任务二:打水印
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"打水印 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];
//3.任务三:上传图片
NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"上传图片 - %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:1.0];
}];
//4.设置依赖
[operation2 addDependency:operation1]; //任务二依赖任务一
[operation3 addDependency:operation2]; //任务三依赖任务二
//5.创建队列并加入任务
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperations:@[operation3, operation2, operation1] waitUntilFinished:NO];
这就是添加依赖的大体过程。
结语
多线程的出现主要是为了合理利用CPU资源。而在iOS开发中,如果你加载数据的事情也放在主线程来做那么主线程就会由于网络缓慢而卡死(就是界面停着不动了)。
建议是这样的,加载数据的事情放在异步线程来完成。然后刷新UI最好放在主线程,放在异步线程会出现奇奇怪怪的问题。
个人非常喜欢GCD,因为线程依赖的情况还是挺少出现的。而且GCD是C的实现,在一定程度上效率还是很有保障的。