GCD多线程应用
2017-08-09 本文已影响0人
a315c2a13dc5
概念
在GCD中有两个重要的概念:任务和队列。
任务
所要执行的操作。任务有两种执行方式:同步执行和异步执行。
- 同步执行:
- 会阻塞当前线程,直到任务执行完成才会返回当前线程继续运行
- 不具备开启新线程的能力
- 异步执行:
- 不会阻塞当前线程,会立即返回当前线程继续运行
- 具备开启新线程的能力
队列
用于存放任务。队列有两种:串行队列和并发队列。
-
串行队列:
- 任务执行遵循先进先出的顺序,下一个任务在上一个任务执行完成后开始执行
- 创建方式(两种)
dispatch_queue_t serialQueue = dispatch_queue_create("com.apress.mySerialQueue", nil) ; dispatch_queue_t serialQueue = dispatch_queue_create("com.apress.mySerialQueue", DISPATCH_QUEUE_SERIAL) ;
-
并发队列:
- 任务执行遵循先进先出的顺序,下一个任务可以在上一个任务执行完成前开始执行
- 创建方式
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.appress.myConcurrentQueue",DISPATCH_QUEUE_CONCURRENT) ;
- 系统提供了四种全局的并发队列,这些队列通过优先级加以区别。高优先级队列中的任务会比在默认或低优先级队列中的任务先执行,而默认级别队列的优先级又高于低优先级队列。被设置成后台级别的队列,它会等待所有比它级别高的队列中的任务执行完或CPU空闲的时候才会执行自己的任务
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) ;
字段 优先级 DISPATCH_QUEUE_PRIORITY_HIGH 高优先级 DISPATCH_QUEUE_PRIORITY_DEFAULT 默认优先级 DISPATCH_QUEUE_PRIORITY_LOW 低优先级 DISPATCH_QUEUE_PRIORITY_BACKGROUND 后台级别 -
主队列:
除了串行队列和并发队列,还有一种特殊的队列——主队列。- 是串行队列
- 所有放在主队列中的任务都会放到主线程中执行
- 可通过
dispatch_get_main_queue()
获得
GCD的多线程使用
使用步骤
- 创建队列
- 向队列中添加任务:
- 通过
dispatch_async
进行异步添加 - 通过
dispatch_sync
进行同步添加
- 通过
使用方式
由于存在不同的队列和任务执行方式,因此有多种组合方式来使用。
- 并发队列+同步执行
- (void)test {
NSLog(@"=============begin") ;
dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",DISPATCH_QUEUE_CONCURRENT) ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"1=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"2=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"3=========%@",[NSThread currentThread]) ;
}
}) ;
NSLog(@"=============end") ;
}
打印结果为:
2017-05-03 14:59:35.976 test[1022:28719] =============begin
2017-05-03 14:59:35.977 test[1022:28719] 1=========<NSThread: 0x600000071240>{number = 1, name = main}
2017-05-03 14:59:35.977 test[1022:28719] 1=========<NSThread: 0x600000071240>{number = 1, name = main}
2017-05-03 14:59:35.977 test[1022:28719] 2=========<NSThread: 0x600000071240>{number = 1, name = main}
2017-05-03 14:59:35.977 test[1022:28719] 2=========<NSThread: 0x600000071240>{number = 1, name = main}
2017-05-03 14:59:35.977 test[1022:28719] 3=========<NSThread: 0x600000071240>{number = 1, name = main}
2017-05-03 14:59:35.977 test[1022:28719] 3=========<NSThread: 0x600000071240>{number = 1, name = main}
2017-05-03 14:59:35.978 test[1022:28719] =============end
- 不会开启新线程,而是在当前线程执行
- 任务按照顺序一个一个执行
- 会阻塞当前线程
- 并发队列+异步执行
- (void)test {
NSLog(@"=============begin") ;
dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",DISPATCH_QUEUE_CONCURRENT) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"1=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"2=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"3=========%@",[NSThread currentThread]) ;
}
}) ;
NSLog(@"=============end") ;
}
打印结果为:
2017-05-03 15:04:37.047 test[1064:39634] =============begin
2017-05-03 15:04:37.047 test[1064:39634] =============end
2017-05-03 15:04:37.048 test[1064:39685] 2=========<NSThread: 0x60800007bc00>{number = 4, name = (null)}
2017-05-03 15:04:37.048 test[1064:39690] 1=========<NSThread: 0x60800007bd00>{number = 3, name = (null)}
2017-05-03 15:04:37.048 test[1064:39684] 3=========<NSThread: 0x60800007bfc0>{number = 5, name = (null)}
2017-05-03 15:04:37.048 test[1064:39685] 2=========<NSThread: 0x60800007bc00>{number = 4, name = (null)}
2017-05-03 15:04:37.048 test[1064:39690] 1=========<NSThread: 0x60800007bd00>{number = 3, name = (null)}
2017-05-03 15:04:37.049 test[1064:39684] 3=========<NSThread: 0x60800007bfc0>{number = 5, name = (null)}
- 开启了多个新线程,并且在各自的新线程中执行
- 任务交替着同时执行
- 不会阻塞当前线程
- 串行队列+同步执行
- (void)test {
NSLog(@"=============begin") ;
dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",nil) ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"1=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"2=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"3=========%@",[NSThread currentThread]) ;
}
}) ;
NSLog(@"=============end") ;
}
打印结果为:
2017-05-03 15:10:33.497 test[1133:50233] =============begin
2017-05-03 15:10:33.497 test[1133:50233] 1=========<NSThread: 0x608000063800>{number = 1, name = main}
2017-05-03 15:10:33.498 test[1133:50233] 1=========<NSThread: 0x608000063800>{number = 1, name = main}
2017-05-03 15:10:33.498 test[1133:50233] 2=========<NSThread: 0x608000063800>{number = 1, name = main}
2017-05-03 15:10:33.498 test[1133:50233] 2=========<NSThread: 0x608000063800>{number = 1, name = main}
2017-05-03 15:10:33.499 test[1133:50233] 3=========<NSThread: 0x608000063800>{number = 1, name = main}
2017-05-03 15:10:33.499 test[1133:50233] 3=========<NSThread: 0x608000063800>{number = 1, name = main}
2017-05-03 15:10:33.499 test[1133:50233] =============end
- 不会开启新线程,而是在当前线程执行
- 任务按照顺序一个一个执行
- 会阻塞当前线程
- 串行队列+异步执行
- (void)test {
NSLog(@"=============begin") ;
dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",nil) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"1=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"2=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"3=========%@",[NSThread currentThread]) ;
}
}) ;
NSLog(@"=============end") ;
}
打印结果为:
2017-05-03 15:13:35.786 test[1168:56495] =============begin
2017-05-03 15:13:35.787 test[1168:56495] =============end
2017-05-03 15:13:35.787 test[1168:56601] 1=========<NSThread: 0x608000270200>{number = 3, name = (null)}
2017-05-03 15:13:35.787 test[1168:56601] 1=========<NSThread: 0x608000270200>{number = 3, name = (null)}
2017-05-03 15:13:35.787 test[1168:56601] 2=========<NSThread: 0x608000270200>{number = 3, name = (null)}
2017-05-03 15:13:35.787 test[1168:56601] 2=========<NSThread: 0x608000270200>{number = 3, name = (null)}
2017-05-03 15:13:35.788 test[1168:56601] 3=========<NSThread: 0x608000270200>{number = 3, name = (null)}
2017-05-03 15:13:35.788 test[1168:56601] 3=========<NSThread: 0x608000270200>{number = 3, name = (null)}
- 开启了一个新线程,所有任务都在该新线程中执行
- 任务按照顺序一个一个执行
- 不会阻塞当前线程
- 主队列+同步执行
NSLog(@"=============begin") ;
dispatch_queue_t myQueue = dispatch_get_main_queue() ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"1=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"2=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_sync(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"3=========%@",[NSThread currentThread]) ;
}
}) ;
NSLog(@"=============end") ;
如果在主线程中采用该方式会出现互等卡住的情况。
在子线程中执行的打印结果为:
2017-05-03 15:34:40.630 test[1279:89558] =============begin
2017-05-03 15:34:40.634 test[1279:89501] 1=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
2017-05-03 15:34:40.635 test[1279:89501] 1=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
2017-05-03 15:34:40.636 test[1279:89501] 2=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
2017-05-03 15:34:40.636 test[1279:89501] 2=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
2017-05-03 15:34:40.636 test[1279:89501] 3=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
2017-05-03 15:34:40.636 test[1279:89501] 3=========<NSThread: 0x60000006e3c0>{number = 1, name = main}
2017-05-03 15:34:40.637 test[1279:89558] =============end
- 在主线程中执行
- 任务按照顺序一个一个执行
- 会阻塞当前线程
- 主队列+异步执行
- (void)test {
NSLog(@"=============begin") ;
dispatch_queue_t myQueue = dispatch_get_main_queue() ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"1=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"2=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 2; i++) {
NSLog(@"3=========%@",[NSThread currentThread]) ;
}
}) ;
NSLog(@"=============end") ;
}
打印结果为:
2017-05-03 15:36:10.336 test[1312:93448] =============begin
2017-05-03 15:36:10.337 test[1312:93448] =============end
2017-05-03 15:36:10.347 test[1312:93448] 1=========<NSThread: 0x600000064c80>{number = 1, name = main}
2017-05-03 15:36:10.348 test[1312:93448] 1=========<NSThread: 0x600000064c80>{number = 1, name = main}
2017-05-03 15:36:10.352 test[1312:93448] 2=========<NSThread: 0x600000064c80>{number = 1, name = main}
2017-05-03 15:36:10.358 test[1312:93448] 2=========<NSThread: 0x600000064c80>{number = 1, name = main}
2017-05-03 15:36:10.359 test[1312:93448] 3=========<NSThread: 0x600000064c80>{number = 1, name = main}
2017-05-03 15:36:10.359 test[1312:93448] 3=========<NSThread: 0x600000064c80>{number = 1, name = main}
- 在主线程中执行
- 任务按照顺序一个一个执行
- 不会阻塞当前线程
总结如下:
队列 | 并行队列 | 串行队列 | 主队列 |
---|---|---|---|
同步(sync) | 没有开启新线程,串行执行任务 | 没有开启新线程,串行执行任务 | 没有开启新线程,串行执行任务 |
异步(async) | 有开启新线程,并发执行任务 | 有开启新线程,串行执行任务 | 没有开启新线程,串行执行任务 |
当任务队列为非主队列时,只有异步执行才会开启新线程。如果是并发队列,会开启多条线程,如果是串行队列, 只会开启一条线程。 其他情况下(包括主队列) 都不会开启新线程,并且是串行执行任务。
GCD的其他使用
GCD 栅栏函数
在异步执行任务的过程中,有时候需要控制任务执行的顺序:在第一组任务执行完成后再执行第二组任务,可以通过GCD的栅栏函数dispatch_barrier_async
来实现。当栅栏函数执行完成后才会执行后面的任务。
使用
添加栅栏函数前:
- (void)test {
NSLog(@"=============begin") ;
dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",DISPATCH_QUEUE_CONCURRENT) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 3; i++) {
NSLog(@"1=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 3; i++) {
NSLog(@"2=========%@",[NSThread currentThread]) ;
}
}) ;
// dispatch_barrier_async(myQueue, ^{
// NSLog(@"++++++++++++++++++++++++++++++++++++++++") ;
// }) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 3; i++) {
NSLog(@"3=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 3; i++) {
NSLog(@"4=========%@",[NSThread currentThread]) ;
}
}) ;
NSLog(@"=============end") ;
}
打印结果为:
2017-05-08 15:37:00.970 test[14150:286911] =============begin
2017-05-08 15:37:00.970 test[14150:286911] =============end
2017-05-08 15:37:00.970 test[14150:286950] 2=========<NSThread: 0x60000026b480>{number = 4, name = (null)}
2017-05-08 15:37:00.970 test[14150:286951] 1=========<NSThread: 0x608000267680>{number = 3, name = (null)}
2017-05-08 15:37:00.970 test[14150:286971] 4=========<NSThread: 0x60000026bac0>{number = 6, name = (null)}
2017-05-08 15:37:00.970 test[14150:286953] 3=========<NSThread: 0x60000026b4c0>{number = 5, name = (null)}
2017-05-08 15:37:00.971 test[14150:286950] 2=========<NSThread: 0x60000026b480>{number = 4, name = (null)}
2017-05-08 15:37:00.971 test[14150:286951] 1=========<NSThread: 0x608000267680>{number = 3, name = (null)}
2017-05-08 15:37:00.971 test[14150:286971] 4=========<NSThread: 0x60000026bac0>{number = 6, name = (null)}
2017-05-08 15:37:00.971 test[14150:286953] 3=========<NSThread: 0x60000026b4c0>{number = 5, name = (null)}
2017-05-08 15:37:00.971 test[14150:286950] 2=========<NSThread: 0x60000026b480>{number = 4, name = (null)}
2017-05-08 15:37:00.971 test[14150:286951] 1=========<NSThread: 0x608000267680>{number = 3, name = (null)}
2017-05-08 15:37:00.972 test[14150:286953] 3=========<NSThread: 0x60000026b4c0>{number = 5, name = (null)}
2017-05-08 15:37:00.972 test[14150:286971] 4=========<NSThread: 0x60000026bac0>{number = 6, name = (null)}
添加栅栏函数后:
- (void)test {
NSLog(@"=============begin") ;
dispatch_queue_t myQueue = dispatch_queue_create("com.appress.myQueue",DISPATCH_QUEUE_CONCURRENT) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 3; i++) {
NSLog(@"1=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 3; i++) {
NSLog(@"2=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_barrier_async(myQueue, ^{
NSLog(@"++++++++++++++++++++++++++++++++++++++++") ;
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 3; i++) {
NSLog(@"3=========%@",[NSThread currentThread]) ;
}
}) ;
dispatch_async(myQueue, ^{
for(int i = 0; i < 3; i++) {
NSLog(@"4=========%@",[NSThread currentThread]) ;
}
}) ;
NSLog(@"=============end") ;
}
打印结果为:
2017-05-08 16:02:47.255 test[14241:316852] =============begin
2017-05-08 16:02:47.256 test[14241:316852] =============end
2017-05-08 16:02:47.256 test[14241:316986] 1=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
2017-05-08 16:02:47.256 test[14241:316983] 2=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
2017-05-08 16:02:47.256 test[14241:316986] 1=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
2017-05-08 16:02:47.256 test[14241:316983] 2=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
2017-05-08 16:02:47.256 test[14241:316986] 1=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
2017-05-08 16:02:47.257 test[14241:316983] 2=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
2017-05-08 16:02:47.257 test[14241:316983] ++++++++++++++++++++++++++++++++++++++++
2017-05-08 16:02:47.257 test[14241:316983] 3=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
2017-05-08 16:02:47.257 test[14241:316986] 4=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
2017-05-08 16:02:47.257 test[14241:316983] 3=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
2017-05-08 16:02:47.257 test[14241:316986] 4=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
2017-05-08 16:02:47.257 test[14241:316983] 3=========<NSThread: 0x60800006c2c0>{number = 4, name = (null)}
2017-05-08 16:02:47.258 test[14241:316986] 4=========<NSThread: 0x60000006f440>{number = 3, name = (null)}
注意
- 栅栏函数不能使用全局的并发队列。
GCD的迭代
使用
dispatch_apply(迭代次数, 线程队列(并发队列), ^(size_t index索引) {
执行任务 ;
}) ;
注意
- 开启了子线程来执行任务
- 迭代不是按照顺序的
GCD队列组
异步执行多个耗时操作,当所有操作都执行完毕后再执行某一操作。可以通过使用GCD队列组来实现。
使用
NSLog(@"===============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, ^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"1===============%@",[NSThread currentThread]) ;
}
}) ;
dispatch_group_async(group, queue, ^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"2===============%@",[NSThread currentThread]) ;
}
}) ;
dispatch_group_async(group, queue, ^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"3===============%@",[NSThread currentThread]) ;
}
}) ;
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"===============end") ;
}) ;
打印结果为:
2017-08-08 13:36:21.124 GCD[3643:200121] ===============begin
2017-08-08 13:36:21.125 GCD[3643:200159] 1===============<NSThread: 0x60000007f2c0>{number = 3, name = (null)}
2017-08-08 13:36:21.125 GCD[3643:200156] 3===============<NSThread: 0x608000267100>{number = 5, name = (null)}
2017-08-08 13:36:21.125 GCD[3643:200157] 2===============<NSThread: 0x60800007cac0>{number = 4, name = (null)}
2017-08-08 13:36:21.125 GCD[3643:200159] 1===============<NSThread: 0x60000007f2c0>{number = 3, name = (null)}
2017-08-08 13:36:21.125 GCD[3643:200156] 3===============<NSThread: 0x608000267100>{number = 5, name = (null)}
2017-08-08 13:36:21.125 GCD[3643:200157] 2===============<NSThread: 0x60800007cac0>{number = 4, name = (null)}
2017-08-08 13:36:21.125 GCD[3643:200159] 1===============<NSThread: 0x60000007f2c0>{number = 3, name = (null)}
2017-08-08 13:36:21.125 GCD[3643:200156] 3===============<NSThread: 0x608000267100>{number = 5, name = (null)}
2017-08-08 13:36:21.126 GCD[3643:200157] 2===============<NSThread: 0x60800007cac0>{number = 4, name = (null)}
2017-08-08 13:36:21.126 GCD[3643:200159] 1===============<NSThread: 0x60000007f2c0>{number = 3, name = (null)}
2017-08-08 13:36:21.126 GCD[3643:200156] 3===============<NSThread: 0x608000267100>{number = 5, name = (null)}
2017-08-08 13:36:21.126 GCD[3643:200157] 2===============<NSThread: 0x60800007cac0>{number = 4, name = (null)}
2017-08-08 13:36:21.132 GCD[3643:200121] ===============end
如果dispatch_group_async
的操作中有延时回调,那么在所有回调完成前就会执行dispatch_group_notify
。
typedef void (^resultBlock) () ;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"===============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, ^{
[self testWithBlock:^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"1===============%@",[NSThread currentThread]) ;
}
}] ;
}) ;
dispatch_group_async(group, queue, ^{
[self testWithBlock:^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"2===============%@",[NSThread currentThread]) ;
}
}] ;
}) ;
dispatch_group_async(group, queue, ^{
[self testWithBlock:^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"3===============%@",[NSThread currentThread]) ;
}
}] ;
}) ;
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"===============end") ;
}) ;
}
- (void)testWithBlock:(resultBlock)block {
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)) ;
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT) ;
dispatch_after(time, queue, ^{
block() ;
}) ;
}
打印结果为:
2017-08-08 14:40:25.811 GCD[16467:291922] ===============begin
2017-08-08 14:40:26.048 GCD[16467:291922] ===============end
2017-08-08 14:40:28.007 GCD[16467:291980] 1===============<NSThread: 0x60000007c900>{number = 3, name = (null)}
2017-08-08 14:40:28.007 GCD[16467:291979] 3===============<NSThread: 0x608000262100>{number = 4, name = (null)}
2017-08-08 14:40:28.007 GCD[16467:291982] 2===============<NSThread: 0x60000007c340>{number = 5, name = (null)}
2017-08-08 14:40:28.008 GCD[16467:291979] 3===============<NSThread: 0x608000262100>{number = 4, name = (null)}
2017-08-08 14:40:28.008 GCD[16467:291980] 1===============<NSThread: 0x60000007c900>{number = 3, name = (null)}
2017-08-08 14:40:28.008 GCD[16467:291982] 2===============<NSThread: 0x60000007c340>{number = 5, name = (null)}
2017-08-08 14:40:28.008 GCD[16467:291979] 3===============<NSThread: 0x608000262100>{number = 4, name = (null)}
2017-08-08 14:40:28.008 GCD[16467:291980] 1===============<NSThread: 0x60000007c900>{number = 3, name = (null)}
2017-08-08 14:40:28.008 GCD[16467:291982] 2===============<NSThread: 0x60000007c340>{number = 5, name = (null)}
2017-08-08 14:40:28.009 GCD[16467:291979] 3===============<NSThread: 0x608000262100>{number = 4, name = (null)}
2017-08-08 14:40:28.009 GCD[16467:291980] 1===============<NSThread: 0x60000007c900>{number = 3, name = (null)}
2017-08-08 14:40:28.009 GCD[16467:291982] 2===============<NSThread: 0x60000007c340>{number = 5, name = (null)}
通过dispatch_group_enter(group)
和dispatch_group_leave(group)
的配合使用来解决这个问题。
typedef void (^resultBlock) () ;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"===============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_group_async(group, queue, ^{
[self testWithBlock:^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"1===============%@",[NSThread currentThread]) ;
}
dispatch_group_leave(group) ;
}] ;
}) ;
dispatch_group_enter(group) ;
dispatch_group_async(group, queue, ^{
[self testWithBlock:^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"2===============%@",[NSThread currentThread]) ;
}
dispatch_group_leave(group) ;
}] ;
}) ;
dispatch_group_enter(group) ;
dispatch_group_async(group, queue, ^{
[self testWithBlock:^{
for(int i = 0 ; i < 4 ; i ++) {
NSLog(@"3===============%@",[NSThread currentThread]) ;
}
dispatch_group_leave(group) ;
}] ;
}) ;
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"===============end") ;
}) ;
}
- (void)testWithBlock:(resultBlock)block {
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0*NSEC_PER_SEC)) ;
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT) ;
dispatch_after(time, queue, ^{
block() ;
}) ;
}
@end
打印结果为:
2017-08-08 15:03:07.867 GCD[16548:311040] ===============begin
2017-08-08 15:03:09.868 GCD[16548:311101] 2===============<NSThread: 0x6000000773c0>{number = 5, name = (null)}
2017-08-08 15:03:09.868 GCD[16548:311098] 3===============<NSThread: 0x60000007ab40>{number = 3, name = (null)}
2017-08-08 15:03:09.868 GCD[16548:311099] 1===============<NSThread: 0x608000071d80>{number = 4, name = (null)}
2017-08-08 15:03:09.869 GCD[16548:311101] 2===============<NSThread: 0x6000000773c0>{number = 5, name = (null)}
2017-08-08 15:03:09.869 GCD[16548:311098] 3===============<NSThread: 0x60000007ab40>{number = 3, name = (null)}
2017-08-08 15:03:09.869 GCD[16548:311099] 1===============<NSThread: 0x608000071d80>{number = 4, name = (null)}
2017-08-08 15:03:09.869 GCD[16548:311101] 2===============<NSThread: 0x6000000773c0>{number = 5, name = (null)}
2017-08-08 15:03:09.869 GCD[16548:311098] 3===============<NSThread: 0x60000007ab40>{number = 3, name = (null)}
2017-08-08 15:03:09.869 GCD[16548:311099] 1===============<NSThread: 0x608000071d80>{number = 4, name = (null)}
2017-08-08 15:03:09.869 GCD[16548:311101] 2===============<NSThread: 0x6000000773c0>{number = 5, name = (null)}
2017-08-08 15:03:09.870 GCD[16548:311098] 3===============<NSThread: 0x60000007ab40>{number = 3, name = (null)}
2017-08-08 15:03:09.870 GCD[16548:311099] 1===============<NSThread: 0x608000071d80>{number = 4, name = (null)}
2017-08-08 15:03:09.870 GCD[16548:311040] ===============end
通过这种方法可以解决诸如:多个网络请求全部完成以后再进行某项操作的问题。