概念
在GCD中有兩個重要的概念:任務(wù)和隊列狞尔。
任務(wù)
所要執(zhí)行的操作潘靖。任務(wù)有兩種執(zhí)行方式:同步執(zhí)行和異步執(zhí)行降淮。
- 同步執(zhí)行:
- 會阻塞當(dāng)前線程逐沙,直到任務(wù)執(zhí)行完成才會返回當(dāng)前線程繼續(xù)運行
- 不具備開啟新線程的能力
- 異步執(zhí)行:
- 不會阻塞當(dāng)前線程洛史,會立即返回當(dāng)前線程繼續(xù)運行
- 具備開啟新線程的能力
隊列
用于存放任務(wù)。隊列有兩種:串行隊列和并發(fā)隊列酱吝。
-
串行隊列:
- 任務(wù)執(zhí)行遵循先進(jìn)先出的順序也殖,下一個任務(wù)在上一個任務(wù)執(zhí)行完成后開始執(zhí)行
- 創(chuàng)建方式(兩種)
dispatch_queue_t serialQueue = dispatch_queue_create("com.apress.mySerialQueue", nil) ; dispatch_queue_t serialQueue = dispatch_queue_create("com.apress.mySerialQueue", DISPATCH_QUEUE_SERIAL) ;
-
并發(fā)隊列:
- 任務(wù)執(zhí)行遵循先進(jìn)先出的順序,下一個任務(wù)可以在上一個任務(wù)執(zhí)行完成前開始執(zhí)行
- 創(chuàng)建方式
dispatch_queue_t concurrentQueue = dispatch_queue_create("com.appress.myConcurrentQueue",DISPATCH_QUEUE_CONCURRENT) ;
- 系統(tǒng)提供了四種全局的并發(fā)隊列务热,這些隊列通過優(yōu)先級加以區(qū)別忆嗜。高優(yōu)先級隊列中的任務(wù)會比在默認(rèn)或低優(yōu)先級隊列中的任務(wù)先執(zhí)行,而默認(rèn)級別隊列的優(yōu)先級又高于低優(yōu)先級隊列崎岂。被設(shè)置成后臺級別的隊列捆毫,它會等待所有比它級別高的隊列中的任務(wù)執(zhí)行完或CPU空閑的時候才會執(zhí)行自己的任務(wù)
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) ;
字段 優(yōu)先級 DISPATCH_QUEUE_PRIORITY_HIGH 高優(yōu)先級 DISPATCH_QUEUE_PRIORITY_DEFAULT 默認(rèn)優(yōu)先級 DISPATCH_QUEUE_PRIORITY_LOW 低優(yōu)先級 DISPATCH_QUEUE_PRIORITY_BACKGROUND 后臺級別 -
主隊列:
除了串行隊列和并發(fā)隊列,還有一種特殊的隊列——主隊列冲甘。- 是串行隊列
- 所有放在主隊列中的任務(wù)都會放到主線程中執(zhí)行
- 可通過
dispatch_get_main_queue()
獲得
GCD的多線程使用
使用步驟
- 創(chuàng)建隊列
- 向隊列中添加任務(wù):
- 通過
dispatch_async
進(jìn)行異步添加 - 通過
dispatch_sync
進(jìn)行同步添加
- 通過
使用方式
由于存在不同的隊列和任務(wù)執(zhí)行方式绩卤,因此有多種組合方式來使用。
- 并發(fā)隊列+同步執(zhí)行
- (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") ;
}
打印結(jié)果為:
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
- 不會開啟新線程江醇,而是在當(dāng)前線程執(zhí)行
- 任務(wù)按照順序一個一個執(zhí)行
- 會阻塞當(dāng)前線程
- 并發(fā)隊列+異步執(zhí)行
- (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") ;
}
打印結(jié)果為:
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)}
- 開啟了多個新線程濒憋,并且在各自的新線程中執(zhí)行
- 任務(wù)交替著同時執(zhí)行
- 不會阻塞當(dāng)前線程
- 串行隊列+同步執(zhí)行
- (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") ;
}
打印結(jié)果為:
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
- 不會開啟新線程,而是在當(dāng)前線程執(zhí)行
- 任務(wù)按照順序一個一個執(zhí)行
- 會阻塞當(dāng)前線程
- 串行隊列+異步執(zhí)行
- (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") ;
}
打印結(jié)果為:
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)}
- 開啟了一個新線程陶夜,所有任務(wù)都在該新線程中執(zhí)行
- 任務(wù)按照順序一個一個執(zhí)行
- 不會阻塞當(dāng)前線程
- 主隊列+同步執(zhí)行
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") ;
如果在主線程中采用該方式會出現(xiàn)互等卡住的情況凛驮。
在子線程中執(zhí)行的打印結(jié)果為:
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
- 在主線程中執(zhí)行
- 任務(wù)按照順序一個一個執(zhí)行
- 會阻塞當(dāng)前線程
- 主隊列+異步執(zhí)行
- (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") ;
}
打印結(jié)果為:
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}
- 在主線程中執(zhí)行
- 任務(wù)按照順序一個一個執(zhí)行
- 不會阻塞當(dāng)前線程
總結(jié)如下:
隊列 | 并行隊列 | 串行隊列 | 主隊列 |
---|---|---|---|
同步(sync) | 沒有開啟新線程,串行執(zhí)行任務(wù) | 沒有開啟新線程条辟,串行執(zhí)行任務(wù) | 沒有開啟新線程黔夭,串行執(zhí)行任務(wù) |
異步(async) | 有開啟新線程,并發(fā)執(zhí)行任務(wù) | 有開啟新線程羽嫡,串行執(zhí)行任務(wù) | 沒有開啟新線程本姥,串行執(zhí)行任務(wù) |
當(dāng)任務(wù)隊列為非主隊列時,只有異步執(zhí)行才會開啟新線程杭棵。如果是并發(fā)隊列,會開啟多條線程婚惫,如果是串行隊列, 只會開啟一條線程。 其他情況下(包括主隊列) 都不會開啟新線程,并且是串行執(zhí)行任務(wù)。
GCD的其他使用
GCD 柵欄函數(shù)
在異步執(zhí)行任務(wù)的過程中辰妙,有時候需要控制任務(wù)執(zhí)行的順序:在第一組任務(wù)執(zhí)行完成后再執(zhí)行第二組任務(wù),可以通過GCD的柵欄函數(shù)dispatch_barrier_async
來實現(xiàn)甫窟。當(dāng)柵欄函數(shù)執(zhí)行完成后才會執(zhí)行后面的任務(wù)密浑。
使用
添加?xùn)艡诤瘮?shù)前:
- (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") ;
}
打印結(jié)果為:
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)}
添加?xùn)艡诤瘮?shù)后:
- (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") ;
}
打印結(jié)果為:
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)}
注意
- 柵欄函數(shù)不能使用全局的并發(fā)隊列。
GCD的迭代
使用
dispatch_apply(迭代次數(shù), 線程隊列(并發(fā)隊列), ^(size_t index索引) {
執(zhí)行任務(wù) ;
}) ;
注意
- 開啟了子線程來執(zhí)行任務(wù)
- 迭代不是按照順序的
GCD隊列組
異步執(zhí)行多個耗時操作粗井,當(dāng)所有操作都執(zhí)行完畢后再執(zhí)行某一操作尔破。可以通過使用GCD隊列組來實現(xiàn)浇衬。
使用
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") ;
}) ;
打印結(jié)果為:
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
的操作中有延時回調(diào)懒构,那么在所有回調(diào)完成前就會執(zhí)行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() ;
}) ;
}
打印結(jié)果為:
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
打印結(jié)果為:
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
通過這種方法可以解決諸如:多個網(wǎng)絡(luò)請求全部完成以后再進(jìn)行某項操作的問題胆剧。