iOS 多线程-GCD
链接
NSThread
(1)使用NSThread对象建立一个线程非常方便
(2)但是!要使用NSThread管理多个线程非常困难,不推荐使用
(3)技巧!使用[NSThread currentThread]跟踪任务所在线程,适用于这三种技术
NSOperation/NSOperationQueue
(1)是使用GCD实现的一套Objective-C的API
(2)是面向对象的线程技术
(3)提供了一些在GCD中不容易实现的特性,如:限制最大并发数量、操作之间的依赖关系
GCD —— Grand Central Dispatch
(1)是基于C语言的底层API
(2)用Block定义任务,使用起来非常灵活便捷
(3)提供了更多的控制能力以及操作队列中所不能使用的底层函数
GCD的基本思想是就将操作s放在队列s中去执行
操作使用Blocks定义
队列负责调度任务执行所在的线程以及具体的执行时间
队列的特点是先进先出(FIFO)的,新添加至对列的操作都会排在队尾
提示
GCD的函数都是以dispatch(分派、调度)开头的
队列
dispatch_queue_t
串行队列,队列中的任务只会顺序执行
并行队列,队列中的任务通常会并发执行
操作
dispatch_async 异步操作,会并发执行,无法确定任务的执行顺序
dispatch_sync 同步操作,会依次顺序执行,能够决定任务的执行顺序
操作使用Blocks定义
队列负责调度任务执行所在的线程以及具体的执行时间
队列的特点是先进先出(FIFO)的,新添加至对列的操作都会排在队尾
提示
GCD的函数都是以dispatch(分派、调度)开头的
队列
dispatch_queue_t
串行队列,队列中的任务只会顺序执行
并行队列,队列中的任务通常会并发执行
操作
dispatch_async 异步操作,会并发执行,无法确定任务的执行顺序
dispatch_sync 同步操作,会依次顺序执行,能够决定任务的执行顺序
GCD
#import "testVC.h" @implementation testVC -(void)viewDidLoad { [super viewDidLoad]; //队列都是 先进先出 //[self gcdDemo1]; // [self gcdDemo2]; // [self gcdDemo3]; [self gcdDemo4]; } #pragma mark - GCD
#pragma mark -同步任务的阻塞
-(void)gcdDemo5
{
dispatch_queue_t q=dispatch_queue_create("com.test", DISPATCH_QUEUE_SERIAL);
dispatch_sync(q, ^{
NSLog(@"sync");
//同步任务里面嵌套同步任务,会造成阻塞
dispatch_sync(q, ^{
NSLog(@"sync2");
});
});
} #pragma mark - 主(线程)队列,保证操作在主线程上执行 -(void)gcdDemo4 { //每一个应用都只有一个主线程 //为什么需要在主线程上工作呢? //在iOS开发中,所有UI的更新工作,都必须在主线程上执行 //在主线程中只能用async 异步方法 dispatch_queue_t q=dispatch_get_main_queue(); // //主线程 // //阻塞了 // dispatch_sync(q, ^{ // NSLog(@" come on"); // }); //异步任务,在主线程上运行,同时是保持队形的 for (int i=0; i<10; i++) { dispatch_async(q, ^{ NSLog(@"async,%@,%d",[NSThread currentThread],i);//主线程 }); } } #pragma mark - 全局队列(苹果为了方便多线程的设计,提供一个全局队列,供所有的app共同使用) -(void)gcdDemo3 { //全局队列与并行队列的区别 //1、不需要创建,直接get就能用 //2、两个队列的执行效果相同 //3、全局队列没有名称,调用时,无法确认准确队列 dispatch_queue_t q=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); for (int i=0; i<10; i++) { //异步任务,并发执行(新线程) dispatch_async(q, ^{ NSLog(@"async,%@,%d",[NSThread currentThread],i);//新线程 }); } for (int i=0; i<10; i++) { //同步任务顺序执行 dispatch_sync(q, ^{ NSLog(@"sync,%@,%d",[NSThread currentThread],i);//主线程 }); } } #pragma mark - 串行(一个接一个,排队跑,保持队形)队列异步任务 -(void)gcdDemo1 { //将操作放在队列中 //在C语言函数中,定义类型,绝大多数的结尾是_t或者ref //串行队列,异步任务,非常有用 //比如 1、先下载图片 2、然后滤镜(高光,红眼) dispatch_queue_t q=dispatch_queue_create("com.test", DISPATCH_QUEUE_SERIAL);//DISPATCH_QUEUE_SERIAL 串行队列 for (int i=0; i<10; i++) { //串行队列的同步任务,同样会在主线程上运行 //提示,在开发中没人用 //同步任务顺序执行 dispatch_sync(q, ^{ NSLog(@"sync,%@,%d",[NSThread currentThread],i);//主线程 }); } //先跑完前面的串行队列,再执行后面的 for (int i=0; i<10; i++) { //异步任务,并发执行(一个新线程),但是如果在串行队列中,仍然会依次顺序执行 dispatch_async(q, ^{ NSLog(@"async,%@,%d",[NSThread currentThread],i);//新线程 }); } } #pragma mark - 并行(并排跑,类似赛跑)队列异步任务 -(void)gcdDemo2 { //这里没有先后顺序,不可控制,也不可控制新建线程数量 dispatch_queue_t q=dispatch_queue_create("com.test", DISPATCH_QUEUE_CONCURRENT);//DISPATCH_QUEUE_CONCURRENT 并行队列 for (int i=0; i<10; i++) { //特点:没有队形,执行顺序程序员不能控制 //应用场景,并发执行任务,没有先后顺序关系 dispatch_async(q, ^{ NSLog(@"async,%@,%d",[NSThread currentThread],i);//新线程 }); } for (int i=0; i<10; i++) { //同步任务顺序执行 dispatch_sync(q, ^{ NSLog(@"sync,%@,%d",[NSThread currentThread],i);//主线程 }); } } @end
// 全局队列,都在主线程上执行,不会死锁 dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); // 并行队列,都在主线程上执行,不会死锁 dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT); // 串行队列异步中嵌套同步(串行队列同步中嵌套同步),会死锁,但是会执行嵌套同步操作之前的代码 dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL); // 主队列执行同步任务,直接死锁 dispatch_queue_t q = dispatch_get_main_queue();
dispatch_sync(q, ^{ NSLog(@"同步任务 %@", [NSThread currentThread]); dispatch_sync(q, ^{ NSLog(@"同步任务 %@", [NSThread currentThread]); }); });
全局队列的本质就是并发队列,
dispatch_get_global_queue(0,0);
参数说明:参数1:代表该任务的优先级,默认写0就行。参数2:苹果保留关键字,一般也写0
全局队列和并发队列的区别
1. 并发队列有名称, 可以跟踪错误, 全局队列没有
2. 在ARC中不需要考虑释放内存, 不允许调用dispatch_release(q);
在MRC中需要手动释放内存, 并发队列Create创建出来的, 在MRC见到create就要release, 全局队列不需要release(只有一个)
3. 全局队列是所有应用程序共享的
GCD除了上面的函数,还有下面常用的
创建单例 dispatch_once_t
延时执行 dispatch_after 只执行一次,执行完后,就不再执行
栅栏函数 dispatch_barrier_async 、dispatch_barrier_sync ,https://www.jianshu.com/p/c3edd6aa75a2
定时器(倒计时) dispatch_source_set_timer,而NSTimer的定时器是在 RunLoop 中实现的,不准确
GCD组 dispatch_group_t
GCD信号量机制 dispatch_semaphore_t
附大神文章:iOS开发系列--并行开发其实很容易