ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
##什么是GCD: 1、GCD是苹果开发的一个多核编程的解决方法,和其它多线程技术方案相比,使用起来更加简单和方便.   2、纯C语言,提供了非常多强大的函数 ## GCD的优势:   1、GCD是苹果公司为多核的并行运算提出的解决方案    2、GCD会自动利用更多的CPU内核(比如双核、四核)    3、GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程) 4、程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码 ##队列和任务: GCD中有2个核心概念   任务:执行什么操作,用block来封装任务。 队列:用来存放任务。 将任务添加到队列中GCD会自动将队列中的任务取出,放到对应的线程中执行。 任务的取出遵循队列的FIFO原则:先进先出,后进后出 。 队列的类型 并发队列:可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务),并发功能只有在异步(dispatch_async)函数下才有效。 1、获得全局的并发队列 ~~~ //dispatch_queue_priority_t priority:队列的优先级 //unsigned long flags:此参数暂时无用,用0即可 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); ~~~ 全局并发队列的优先级 ~~~ #define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高 #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默认(中) #define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低 #define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN// 后台 ~~~ 串行队列:让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)。   1、使用dispatch_queue_create函数创建串行队列 ~~~ //const char *label:队列名称 //dispatch_queue_attr_t attr:队列属性,一般用NULL即可 dispatch_queue_t queue = dispatch_queue_create("cn.XXX",NULL); ~~~ ~~~ dispatch_release(queue); // 非ARC需要释放手动创建的队列 ~~~ 2、使用主队列(跟主线程相关联的队列),主队列是GCD自带的一种特殊的串行队列 放在主队列中的任务,都会放到主线程中执行 使用dispatch_get_main_queue()获得主队列 ~~~ dispatch_queue_t queue = dispatch_get_main_queue(); ~~~ 执行任务: 1、用同步的方式执行任务 ~~~ dispatch_sync(dispatch_queue_t queue, dispatch_block_t block); ~~~ 2、用异步的方式执行任务 ~~~ dispatch_async(dispatch_queue_t queue, dispatch_block_t block); ~~~ 同步和异步的区别: 1、同步:只能在当前线程中执行任务,不具备开启新线程的能力。dispatch_sync 2、异步:可以在新的线程中执行任务,具备开启新线程的能力。 dispatch_async 队列和执行任务方式组合分析: ps 特别注意:使用sync函数往当前串行队列中添加任务,会卡住当前的串行队列 ![](https://box.kancloud.cn/2016-03-07_56dd401028c5b.jpg) ~~~ /** * 异步全局并发 * async并发队列(最常用) * 会创建线程,一般同时开多条 * 并发执行 **/ -(void)asyncGlobalQueue{ //获取全局并发队列 //dispatch_queue_priority_t priority:队列的优先级 //unsigned long flags:此参数暂时无用,用0即可 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //将任务添加到全局队列中去异步执行 dispatch_async(queue, ^{ NSLog(@"------下载图片1----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"-----下载图片2-----%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"----下载图片3------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"-----下载图片4----%@",[NSThread currentThread]); }); } /** * 串行队列(有时候会用) * 会创建线程,一般只开一条 * 串行执行,(一个任务执行完毕后再执行下一个任务) **/ -(void)asyncSerialQueue{ //创建串行队列 //const char *label:队列名称 //dispatch_queue_attr_t attr:队列属性,一般用NULL即可 dispatch_queue_t queue = dispatch_queue_create("cn.XXX",NULL); //将任务添加到串行队列中 异步执行 dispatch_async(queue,^{ NSLog(@"--------下载图片1---------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------下载图片2---------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------下载图片3---------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------下载图片4---------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------下载图片5---------%@",[NSThread currentThread]); }); } /** * async --主队列(很常用) **/ -(void)asyncMainQueue{ //主队列(添加到主队列中的任务,都会自动放到主线程中去执行) dispatch_queue_t queue = dispatch_get_main_queue(); //添加任务到主队列中异步执行 dispatch_async(queue, ^{ NSLog(@"--------下载图片1---------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------下载图片2---------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------下载图片3---------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------下载图片4---------%@",[NSThread currentThread]); }); dispatch_async(queue, ^{ NSLog(@"--------下载图片5---------%@",[NSThread currentThread]); }); } /** * sync --主队列(不能用,会卡死) **/ -(void)syncMainQueue{ //主队列(添加到主队列中的任务,都会自动放到线程中去执行) dispatch_queue_t queue = dispatch_get_main_queue(); //将任务添加到主队列中同步执行 dispatch_sync(queue, ^{ NSLog(@"--------下载图片1---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片2---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片3---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片4---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片5---------%@",[NSThread currentThread]); }); } /** * sync --并发队列 * 不会创建线程 * 串行执行(一个任务执行完毕后再执行下一个任务) * 并发队列失去了并发的功能 **/ -(void)syncGlobalQueue{ //获取全局的并发队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //将任务添加到全局并发队列中同步执行 dispatch_sync(queue, ^{ NSLog(@"--------下载图片1---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片2---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片3---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片4---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片5---------%@",[NSThread currentThread]); }); } /** * sync --串行队列 * 不会创建线程 * 串行执行(一个任务执行完毕后再执行下一个任务) **/ -(void)syncSerialQueue{ //创建一个串行队列 dispatch_queue_t queue = dispatch_queue_create("cn.xxx", NULL); //将任务添加到串行队列中同步执行 dispatch_sync(queue, ^{ NSLog(@"--------下载图片1---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片2---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片3---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片4---------%@",[NSThread currentThread]); }); dispatch_sync(queue, ^{ NSLog(@"--------下载图片5---------%@",[NSThread currentThread]); }); } ~~~ 一次性执行: ~~~ //一次性执行 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ //<#code to be executed once#> }); ~~~ 延时执行: ~~~ //延时执行(2秒) double delayInSeconds = 2; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ // <#code to be executed after a specified delay#> }); ~~~ 线程组:后台并发执行线程,等所有线程执行结束后再汇总执行结果 ~~~ //1、获取线程组 dispatch_group_t group = dispatch_group_create(); //2、并行执行线程 dispatch_group_async(group, queue, ^{ //并发执行线程一 ); ispatch_group_async(group, queue, ^{ //并发执行线程二 }); //3、所有线程执行完成后调用 dispatch_group_notify(group, queue, ^{ //汇总结果 }); ~~~ ## 线程间通信 从子线程回到主线程 ~~~ dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{     // 执行耗时的异步操作...       dispatch_async(dispatch_get_main_queue(), ^{         // 回到主线程,执行UI刷新操作         }); }); ~~~ 例子:子线程下载图片,下载后更新界面的imageView. ~~~ -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ //子线程下载图片 NSURL *url = [NSURL URLWithString:@"http://d.hiphotos.baidu.com/image/pic/item/37d3d539b6003af3290eaf5d362ac65c1038b652.jpg"]; NSData *data = [NSData dataWithContentsOfURL:url]; UIImage *image = [UIImage imageWithData:data]; //回到主线程 dispatch_queue_t mainQueue = dispatch_get_main_queue(); dispatch_async(mainQueue, ^{ self.imageView.image = image; }); }); } ~~~