-
简介:
为什么要用 GCD 呢?因为 GCD 有很多好处啊,具体如下:
GCD 可用于多核的并行运算
GCD 会自动利用更多的 CPU 内核(比如双核、四核)
GCD 会自动管理线程的生命周期(创建线程、调度任务、销毁线程)
程序员只需要告诉 GCD 想要执行什么任务,不需要编写任何线程管理代码
既然 GCD 有这么多的好处,那么下面我们就来系统的学习一下 GCD 的使用方法。
目录:
队列创建
同步异步
线程间通讯
延迟执行(dispatch_after)
定时器(dispatch_timer)
一次执行(dispatch_once)
迭代(dispatch_apply)
队列组(dispatch_group_notify)
等待(dispatch_group_wait)
信号(dispatch_semaphore_t)
并发控制通过信号实现
-
队列创建:
//串行队列 dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_SERIAL); //并行队列 dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_CONCURRENT); //全局并行队列 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //主线程队列 dispatch_queue_t queue = dispatch_get_main_queue();
-
同步异步:
- (void)asyncAction { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_async(queue, ^{ NSLog(@"async---%@",[NSThread currentThread]); }); } - (void)syncAction { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_sync(queue, ^{ NSLog(@"sync---%@",[NSThread currentThread]); }); }
输出: ---<NSThread: 0x60c00026bd40>{number = 5, name = (null)} ---<NSThread: 0x60000007f300>{number = 1, name = main}
-
线程间通讯:
- (void)asyncToSyncAction { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"---%@",[NSThread currentThread]); // 回到主线程 dispatch_async(dispatch_get_main_queue(), ^{ NSLog(@"---%@",[NSThread currentThread]); }); }); }
输出: ---<NSThread: 0x60c00026bd40>{number = 5, name = (null)} ---<NSThread: 0x60000007f300>{number = 1, name = main}
-
栅栏(dispatch_barrier_async):
- (void)barrierAction { dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_CONCURRENT); for (int i = 0; i < 10; i ++) { dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"1---%@",[NSThread currentThread]); }); } //barrier dispatch_barrier_async(queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"[Barrier: ---%@",[NSThread currentThread]); }); for (int i = 0; i < 10; i ++) { dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"3---%@",[NSThread currentThread]); }); } }
输出: 2018-03-20 17:57:39.417137+0800 GCD[55856:2568834] 1---<NSThread: 0x604000074780>{number = 6, name = (null)} 2018-03-20 17:57:39.417137+0800 GCD[55856:2568833] 1---<NSThread: 0x6000002701c0>{number = 3, name = (null)} 2018-03-20 17:57:39.417138+0800 GCD[55856:2568832] 1---<NSThread: 0x60c00007e7c0>{number = 4, name = (null)} 2018-03-20 17:57:39.417148+0800 GCD[55856:2568835] 1---<NSThread: 0x60800007d7c0>{number = 5, name = (null)} 2018-03-20 17:57:39.417197+0800 GCD[55856:2568853] 1---<NSThread: 0x600000270080>{number = 7, name = (null)} 2018-03-20 17:57:39.417247+0800 GCD[55856:2568855] 1---<NSThread: 0x6040000754c0>{number = 8, name = (null)} 2018-03-20 17:57:39.417308+0800 GCD[55856:2568856] 1---<NSThread: 0x60000026fac0>{number = 10, name = (null)} 2018-03-20 17:57:39.417329+0800 GCD[55856:2568854] 1---<NSThread: 0x604000074a80>{number = 9, name = (null)} 2018-03-20 17:57:39.417344+0800 GCD[55856:2568857] 1---<NSThread: 0x604000074380>{number = 11, name = (null)} 2018-03-20 17:57:39.417361+0800 GCD[55856:2568858] 1---<NSThread: 0x60c00007e800>{number = 12, name = (null)} 2018-03-20 17:57:41.420468+0800 GCD[55856:2568858] [Barrier: ---<NSThread: 0x60c00007e800>{number = 12, name = (null)} 2018-03-20 17:57:43.423862+0800 GCD[55856:2568858] 3---<NSThread: 0x60c00007e800>{number = 12, name = (null)} 2018-03-20 17:57:43.423827+0800 GCD[55856:2568855] 3---<NSThread: 0x6040000754c0>{number = 8, name = (null)} 2018-03-20 17:57:43.423826+0800 GCD[55856:2568854] 3---<NSThread: 0x604000074a80>{number = 9, name = (null)} 2018-03-20 17:57:43.423827+0800 GCD[55856:2568857] 3---<NSThread: 0x604000074380>{number = 11, name = (null)} 2018-03-20 17:57:43.423855+0800 GCD[55856:2568853] 3---<NSThread: 0x600000270080>{number = 7, name = (null)} 2018-03-20 17:57:43.423823+0800 GCD[55856:2568856] 3---<NSThread: 0x60000026fac0>{number = 10, name = (null)} 2018-03-20 17:57:43.423949+0800 GCD[55856:2568834] 3---<NSThread: 0x604000074780>{number = 6, name = (null)} 2018-03-20 17:57:43.423952+0800 GCD[55856:2568833] 3---<NSThread: 0x6000002701c0>{number = 3, name = (null)} 2018-03-20 17:57:43.423960+0800 GCD[55856:2568835] 3---<NSThread: 0x60800007d7c0>{number = 5, name = (null)} 2018-03-20 17:57:43.423964+0800 GCD[55856:2568832] 3---<NSThread: 0x60c00007e7c0>{number = 4, name = (null)}
-
延迟执行(dispatch_after):
- (void)afterAction { NSLog(@"[After]: begin currentThread---%@",[NSThread currentThread]); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"[After]: main ---%@",[NSThread currentThread]); }); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSLog(@"[After]: global ---%@",[NSThread currentThread]); }); }
输出: 2018-03-20 18:01:33.749444+0800 GCD[55856:2568766] [After]: begin currentThread---<NSThread: 0x60000006e280>{number = 1, name = main} 2018-03-20 18:01:35.928257+0800 GCD[55856:2568766] [After]: main ---<NSThread: 0x60000006e280>{number = 1, name = main} 2018-03-20 18:01:35.928274+0800 GCD[55856:2571380] [After]: global ---<NSThread: 0x60c00007e280>{number = 13, name = (null)}
-
定时器(dispatch_timer):
@property(nonatomic,strong) dispatch_source_t tTimer; - (void)timerAction { NSLog(@"[Timer]: begin currentThread---%@",[NSThread currentThread]); if (!self.tTimer) { self.tTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue()); NSLog(@"self.tTimer = %@",self.tTimer); dispatch_source_set_timer(self.tTimer, dispatch_walltime(NULL, 0 * NSEC_PER_SEC), 0.32 * NSEC_PER_SEC, 0); dispatch_source_set_event_handler(self.tTimer, ^{ NSLog(@"1111"); }); dispatch_resume(self.tTimer); } else { dispatch_source_cancel(self.tTimer); self.tTimer = nil; } // dispatch_suspend(self.tTimer); // dispatch_source_cancel(self.tTimer); // self.tTimer = nil; Crash // dispatch_suspend(self.tTimer); // self.tTimer = nil; Crash }
-
一次执行(dispatch_once):
- (void)onceAction { __block int index = 0; for (int i = 0; i < 10; i ++) { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ index ++; NSLog(@"[Once]:-------index = %d",index); }); } }
输出: 2018-03-20 18:03:17.189632+0800 GCD[55856:2568766] [Once]:-------index = 1
-
迭代(dispatch_apply):
- (void)applyAction { //并行迭代 dispatch_queue_t queue = dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //串行队列迭代与for循环效果一样 //queue = dispatch_queue_t queue = dispatch_queue_create("com.gcd.peace", DISPATCH_QUEUE_SERIAL); NSLog(@"apply---begin"); dispatch_apply(6, queue, ^(size_t index) { NSLog(@"%zd---%@",index, [NSThread currentThread]); [NSThread sleepForTimeInterval:2]; }); NSLog(@"apply---end"); }
并行队列输出: 2018-03-20 18:05:42.458703+0800 GCD[56041:2574450] apply---begin 2018-03-20 18:05:42.459384+0800 GCD[56041:2574450] 0---<NSThread: 0x60c000262bc0>{number = 1, name = main} 2018-03-20 18:05:42.459417+0800 GCD[56041:2574512] 1---<NSThread: 0x60c00027f840>{number = 3, name = (null)} 2018-03-20 18:05:42.459504+0800 GCD[56041:2574499] 4---<NSThread: 0x6080002786c0>{number = 7, name = (null)} 2018-03-20 18:05:42.459504+0800 GCD[56041:2574502] 3---<NSThread: 0x604000270e00>{number = 4, name = (null)} 2018-03-20 18:05:42.459506+0800 GCD[56041:2574500] 5---<NSThread: 0x604000270c00>{number = 6, name = (null)} 2018-03-20 18:05:42.459521+0800 GCD[56041:2574501] 2---<NSThread: 0x608000278a00>{number = 5, name = (null)} 2018-03-20 18:05:44.463743+0800 GCD[56041:2574450] apply---end
串行队列输出: 2018-03-20 18:07:33.988048+0800 GCD[56083:2576141] apply---begin 2018-03-20 18:07:33.988516+0800 GCD[56083:2576141] 0---<NSThread: 0x60c000065740>{number = 1, name = main} 2018-03-20 18:07:35.989109+0800 GCD[56083:2576141] 1---<NSThread: 0x60c000065740>{number = 1, name = main} 2018-03-20 18:07:37.990556+0800 GCD[56083:2576141] 2---<NSThread: 0x60c000065740>{number = 1, name = main} 2018-03-20 18:07:39.992050+0800 GCD[56083:2576141] 3---<NSThread: 0x60c000065740>{number = 1, name = main} 2018-03-20 18:07:41.993583+0800 GCD[56083:2576141] 4---<NSThread: 0x60c000065740>{number = 1, name = main} 2018-03-20 18:07:43.995163+0800 GCD[56083:2576141] 5---<NSThread: 0x60c000065740>{number = 1, name = main} 2018-03-20 18:07:45.995811+0800 GCD[56083:2576141] apply---end
-
队列组(dispatch_group_notify):
- (void)groupNotifyAction { NSLog(@"group---begin"); dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"1---%@",[NSThread currentThread]); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"2---%@",[NSThread currentThread]); }); dispatch_group_notify(group, [self mainQueue], ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"3---%@",[NSThread currentThread]); NSLog(@"group notify"); }); }
输出: 2018-03-20 18:09:47.306064+0800 GCD[56083:2576141] group---begin 2018-03-20 18:09:49.307609+0800 GCD[56083:2576199] 2---<NSThread: 0x60800006ce00>{number = 4, name = (null)} 2018-03-20 18:09:49.307608+0800 GCD[56083:2577770] 1---<NSThread: 0x60400007fac0>{number = 3, name = (null)} 2018-03-20 18:09:51.309380+0800 GCD[56083:2576141] 3---<NSThread: 0x60c000065740>{number = 1, name = main} 2018-03-20 18:09:51.309744+0800 GCD[56083:2576141] group notify
- (void)groupNotify1Action { NSLog(@"group---begin"); dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_enter(group); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"1---%@",[NSThread currentThread]); dispatch_group_leave(group); }); dispatch_group_enter(group); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:5]; NSLog(@"2---%@",[NSThread currentThread]); dispatch_group_leave(group); }); dispatch_group_notify(group, [self mainQueue], ^{ NSLog(@"group notify : %@",[NSThread currentThread]); }); }
输出: 2018-03-20 18:09:53.329762+0800 GCD[56083:2576141] group---begin 2018-03-20 18:09:55.332737+0800 GCD[56083:2576199] 1---<NSThread: 0x60800006ce00>{number = 4, name = (null)} 2018-03-20 18:09:58.331259+0800 GCD[56083:2577770] 2---<NSThread: 0x60400007fac0>{number = 3, name = (null)} 2018-03-20 18:09:58.331676+0800 GCD[56083:2576141] group notify : <NSThread: 0x60c000065740>{number = 1, name = main}
-
等待(dispatch_group_wait):
- (void)groupWaitAction { NSLog(@"group---begin"); dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"1---%@",[NSThread currentThread]); }); dispatch_group_async(group, queue, ^{ [NSThread sleepForTimeInterval:5]; NSLog(@"2---%@",[NSThread currentThread]); }); dispatch_group_wait(group, DISPATCH_TIME_FOREVER); NSLog(@"group---end"); }
输出: 2018-03-20 18:12:57.523759+0800 GCD[56083:2576141] group---begin 2018-03-20 18:12:59.527048+0800 GCD[56083:2579780] 1---<NSThread: 0x600000260780>{number = 5, name = (null)} 2018-03-20 18:13:02.524335+0800 GCD[56083:2577781] 2---<NSThread: 0x60000007fd40>{number = 6, name = (null)} 2018-03-20 18:13:02.524954+0800 GCD[56083:2576141] group---end
-
信号(dispatch_semaphore_t):
//通过信号实现同步功能 - (void)semaphoreAction { NSLog(@"semaphore---begin"); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); dispatch_async(queue, ^{ [NSThread sleepForTimeInterval:2]; NSLog(@"semaphore --- %@",[NSThread currentThread]); dispatch_semaphore_signal(semaphore); }); dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);//信号量=0则阻挡,>0则通过 NSLog(@"semaphore---end"); }
输出: 2018-03-20 18:14:28.265856+0800 GCD[56083:2576141] semaphore---begin 2018-03-20 18:14:30.271145+0800 GCD[56083:2580996] semaphore --- <NSThread: 0x60c000078880>{number = 8, name = (null)} 2018-03-20 18:14:30.271384+0800 GCD[56083:2576141] semaphore---end
//通过信号实现锁 - (void)semaphore1Action { dispatch_queue_t queue = dispatch_get_global_queue(0, 0); dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); for (int i = 0; i < 100; i++) { dispatch_async(queue, ^{ // 相当于加锁 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); NSLog(@"i = %zd semaphore = %@", i, semaphore); // 相当于解锁 dispatch_semaphore_signal(semaphore); }); } }
输出: 2018-03-20 18:16:21.561341+0800 GCD[56217:2582806] i = 0 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.561717+0800 GCD[56217:2582805] i = 1 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.561999+0800 GCD[56217:2582803] i = 2 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.562277+0800 GCD[56217:2582804] i = 3 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.562508+0800 GCD[56217:2582812] i = 4 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.562745+0800 GCD[56217:2582823] i = 5 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.562979+0800 GCD[56217:2582824] i = 6 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.563213+0800 GCD[56217:2582825] i = 7 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.563442+0800 GCD[56217:2582826] i = 8 semaphore = <OS_dispatch_semaphore: 0x60c000084510> 2018-03-20 18:16:21.563671+0800 GCD[56217:2582827] i = 9 semaphore = <OS_dispatch_semaphore: 0x60c000084510>
-
并发控制通过信号实现:
void dispatch_async_limit(dispatch_queue_t queue,NSUInteger limitSemaphoreCount, dispatch_block_t block) { //控制并发数的信号量 static dispatch_semaphore_t limitSemaphore; //专门控制并发等待的线程 static dispatch_queue_t receiverQueue; //使用 dispatch_once而非 lazy 模式,防止可能的多线程抢占问题 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ limitSemaphore = dispatch_semaphore_create(limitSemaphoreCount); receiverQueue = dispatch_queue_create("receiver", DISPATCH_QUEUE_SERIAL); }); // 如不加 receiverQueue 放在主线程会阻塞主线程 dispatch_async(receiverQueue, ^{ //可用信号量后才能继续,否则等待 dispatch_semaphore_wait(limitSemaphore, DISPATCH_TIME_FOREVER); dispatch_async(queue, ^{ !block ? : block(); //在该工作线程执行完成后释放信号量 long semaphore = dispatch_semaphore_signal(limitSemaphore); if (semaphore > 0) { NSLog(@"\n"); } }); }); } - (void)limitAction { for (int i = 0; i < 10; i++) { dispatch_async_limit([self serialQueue],3, ^{ sleep(2); NSLog(@"------i = %d",i); }); } }
输出: 2018-03-20 17:33:45.367914+0800 GCD[55534:2553299] ------i = 1 2018-03-20 17:33:45.367914+0800 GCD[55534:2553303] ------i = 0 2018-03-20 17:33:45.367916+0800 GCD[55534:2553300] ------i = 2 2018-03-20 17:33:45.368276+0800 GCD[55534:2553303] 2018-03-20 17:33:47.373465+0800 GCD[55534:2553300] ------i = 3 2018-03-20 17:33:47.373482+0800 GCD[55534:2553299] ------i = 4 2018-03-20 17:33:47.373496+0800 GCD[55534:2553302] ------i = 5 2018-03-20 17:33:47.373856+0800 GCD[55534:2553300] 2018-03-20 17:33:49.379032+0800 GCD[55534:2553302] ------i = 6 2018-03-20 17:33:49.379048+0800 GCD[55534:2553299] ------i = 7 2018-03-20 17:33:49.379048+0800 GCD[55534:2553303] ------i = 8 2018-03-20 17:33:49.379452+0800 GCD[55534:2553299] 2018-03-20 17:33:51.383480+0800 GCD[55534:2553301] ------i = 9
-
源码: