目錄
- 文字描述
- Dispatch Queue
- dispatch_sync&dispatch_async
- 創建的線程任務有四種執行方式
- Dispatch Group
- Dispatch Block
- dispatch_after
- dispatch_apply
- dispatch_once
- dispatch_barrier_async
- dispatch_set_target_queue
1. 文字描述
GCD英文全稱:Grand Central Dispatch 翻譯就是 宏大的中央調度,是蘋果開發的一種支持并行操作的機制,基于C語言,提供了非常多強大的函數
在了解GCD并使用之前,必須要掌握四個名詞:串行,并發,同步,異步
串行(Serial):
一個任務執行完, 再執行下一個任務
并發 (Concurrent):
多個任務同時執行(自動開啟多個線程),只有在異步函數下才有效
同步(Synchronous):
在當前線程中執行任務,不具備開啟新線程的能力
提交的任務在執行完成后才會返回
同步函數: dispatch_sync()
異步 (Asynchronous):
在新的線程中執行任務, 具備開啟線程的能力
在新線程中執行任務,具備開啟新線程的能力
提交的任務立刻返回,在后臺隊列中執行
異步函數: dispatch_async()
2.Dispatch Queue
Dispatch Queue是執行處理的等待隊列, 按照先進先出(FIFO, First-In-First-Out)的順序進行任務處理.
開發者將需要執行的任務添加到合適的Dispatch Queue中即可,Dispatch Queue會根據任務添加的順序先到先執行,其中有以下幾種隊列:
另外, 隊列分兩種, 一種是串行隊列(Serial Dispatch Queue), 一種是并行隊列(Concurrent Dispatch Queue).
Dispatch Queue的種類 | 說明 |
---|---|
Serial Dispatch Queue | 等待現在執行中處理結束 |
Concurrent Dispatch Queue | 不等待現在執行中處理結束 |
//創建一個串行隊列
dispatch_queue_t serialQueue=dispatch_queue_create("com.serial.queue", DISPATCH_QUEUE_SERIAL);
//創建一個并發隊列
dispatch_queue_t concurrentQueue=dispatch_queue_create("com.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
//第一個參數為隊列名,第二個參數為隊列類型,當然,第二個參數人如果寫NULL,創建出來的也是一個串行隊列。然后我們在異步線程來執行這個隊列:
另外系統為我們準備了兩個隊列
-
main dispatch queue
功能跟主線程一樣,通過dispatch_get_main_queue()來獲取,提交到main queue的任務實際上都是在主線程執行的,所以這是一個串行隊列
dispatch_queue_t queue = dispatch_get_main_queue();
-
global dispatch queues
系統給每個應用提供四個全局的并發隊列,這四個隊列分別有不同的優先級:高、默認、低以及后臺,用戶不能去創建全局隊列,只能根據優先級去獲取:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
3.dispatch_sync&dispatch_async
執行隊列中任務的兩種方式,dispatch_sync是同步任務,dispatch_async是異步任務
1.用同步的方式執行任務(同步:synchronization), 只能在當前線程中執行任務,不具備開啟新線程的能力
/*
* 第一個參數:該任務所在的隊列
* 第二個參數:該任務要做的事情
*/
dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
假如我指定的隊列A是串行隊列,則該隊列中只能有一個線程,也就是說我放在隊列A中的任務,所以必須得一個一個的執行。不僅如此,在上面我們還手動選擇了在隊列A中用同步的方式執行任務,這也限制了,隊列中的任務只能一個一個執行。
假如我指定的隊列A是并行隊列,則該隊列中可以開辟多個線程去執行任務,雖然如此,但由于我們在上面手動選擇了在隊列A中用同步的方式執行線程,所以隊列A中的任務也只能一個一個去執行,不能開辟多線程同時執行。
2.用異步的方式執行任務(異步:asynchronous),可以在新的線程中執行任務,具備開啟新線程的能力。
dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
假如此時我指定的隊列B是并行隊列,則表明該隊列中可以存在多個線程,又因為我們采用的是異步的方式執行任務,所以在這個隊列的任務可以實現同時運行。
假如此時我指定的隊列B是串行隊列,則表明該隊列中,只能有一個線程,所以盡管我采用異步的方式執行任務,但該隊列中的任務還是只能一個一個的運行。
4.創建的線程任務有四種執行方式
1. 串行隊列同步執行任務
- 同步不具有開辟新線程的能力,不會開辟新的線程去執行任務,會在當前程序的主線程中執行任務。
- 按照串行的方式去執行任務
-(void)syncSERIAL{
NSLog(@"star");
//不會開辟新的線程
dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
NSLog(@"SERIAL_work_1 ");
});
dispatch_sync(queue, ^{
NSLog(@"SERIAL_work_2 ");
});
dispatch_sync(queue, ^{
NSLog(@"SERIAL_work_3 ");
});
NSLog(@"end");
}
執行結果
2016-07-20 20:08:09.695 GCD_Demo[8196:1029563] star
2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_1
2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_2
2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] SERIAL_work_3
2016-07-20 20:08:09.696 GCD_Demo[8196:1029563] end
由于是同步操作,不能開辟線程,所以都是在主線程并按照順序執行
2. 串行隊列異步執行任務
- 異步具有創建新線程的能力,會開辟新的線程去執行任務
- 按照串行的方式去執行任務
-(void)asyncSERIAL{
NSLog(@"star");
//會開辟新的線程,但是是串行執行任務
dispatch_queue_t queue=dispatch_queue_create("ki", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"SERIAL_work_1 ");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"SERIAL_work_2 ");
});
dispatch_async(queue, ^{
NSLog(@"SERIAL_work_3 ");
});
NSLog(@"end");
}
執行結果
2016-07-20 20:09:58.494 GCD_Demo[8213:1031268] star
2016-07-20 20:09:58.495 GCD_Demo[8213:1031268] end
2016-07-20 20:10:01.496 GCD_Demo[8213:1031315] SERIAL_work_1
2016-07-20 20:10:03.502 GCD_Demo[8213:1031315] SERIAL_work_2
2016-07-20 20:10:03.502 GCD_Demo[8213:1031315] SERIAL_work_3
因為是異步操作,所以有個編號為2的子線程被開辟,但有因為是串行隊列,所以只開辟了一個線程。最終造就了三個任務順序執行。
3. 并行隊列同步執行任務
- 同步不具有創建新線程的能力,不會開辟新的線程去執行任務,會在當前程序的主線程去執行任務
- 按照同步的方式去執行任務
-(void)syncCONCURRENT{
NSLog(@"star");
//不會開辟新的線程
//串行執行命令
dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"CONCURRENT_work_1 ");
});
dispatch_sync(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"CONCURRENT_work_2 ");
});
dispatch_sync(queue, ^{
NSLog(@"CONCURRENT_work_3 ");
});
NSLog(@"end");
}
執行結果
2016-07-20 20:13:03.753 GCD_Demo[8232:1033759] star
2016-07-20 20:13:06.755 GCD_Demo[8232:1033759] CONCURRENT_work_1
2016-07-20 20:13:08.756 GCD_Demo[8232:1033759] CONCURRENT_work_2
2016-07-20 20:13:08.756 GCD_Demo[8232:1033759] CONCURRENT_work_3
2016-07-20 20:13:08.757 GCD_Demo[8232:1033759] end
雖然并行隊列決定了該隊列中可以有多個線程,但由于是同步操作,不能開辟線程,所以還都是在主線程中按順序執行。
4. 并發隊列異步執行任務(常用)
- 異步具有創建新線程的能力,會開辟新的線程去執行任務,不會在當前程序的主線程去執行任務
- 按照并發的方式去執行任務
-(void)asyncCONCURRENT{
NSLog(@"star");
//一個隊列 為 每個任務開辟一個線程
dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"CONCURRENT_work_1 ");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"CONCURRENT_work_2 ");
});
dispatch_async(queue, ^{
NSLog(@"CONCURRENT_work_3 ");
});
NSLog(@"end");
}
執行結果
2016-07-20 20:18:26.768 GCD_Demo[8256:1038143] star
2016-07-20 20:18:26.768 GCD_Demo[8256:1038143] end
2016-07-20 20:18:26.769 GCD_Demo[8256:1038192] CONCURRENT_work_3
2016-07-20 20:18:28.771 GCD_Demo[8256:1038179] CONCURRENT_work_2
2016-07-20 20:18:29.773 GCD_Demo[8256:1038188] CONCURRENT_work_1
并行隊列可以里可以有多個線程,同步執行的方式又可以開辟多個線程,所以這里實現了多個線程并行執行。
5.Dispatch Group
當我們想在gcd queue中所有的任務執行完畢之后做些特定事情的時候,也就是隊列的同步問題,如果隊列是串行的話,那將該操作最后添加到隊列中即可,但如果隊列是并行隊列的話,這時候就可以利用dispatch_group來實現了,dispatch_group能很方便的解決同步的問題。dispatch_group_create可以創建一個group對象,然后可以添加block到該組里面,下面看下它的一些用法:
-
dispatch_group_notify
是通過異步的方式通知,所以,不會阻塞線程
-(void)asyncGroupNotify
{
NSLog(@"star");
dispatch_group_t group=dispatch_group_create();
dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group_work_1");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:6];
NSLog(@"group_work_2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group_work_3");
});
dispatch_group_notify(group, queue, ^{
NSLog(@"dispatch_group_Notify 結束");
});
}
運行結果
2016-07-21 13:51:40.600 GCD_Demo[9044:1162213] star
2016-07-21 13:51:41.605 GCD_Demo[9044:1162359] group_work_1
2016-07-21 13:51:42.608 GCD_Demo[9044:1162389] group_work_3
2016-07-21 13:51:46.603 GCD_Demo[9044:1162349] group_work_2
2016-07-21 13:51:46.605 GCD_Demo[9044:1162349] dispatch_group_Notify 結束
-
dispatch_group_wait
會阻塞當前線程,知道任務都完成時才會繼續執行下面的代碼
-(void)asyncGroupWait
{
NSLog(@"star");
dispatch_group_t group=dispatch_group_create();
dispatch_queue_t queue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group_work_1");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:6];
NSLog(@"group_work_2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group_work_3");
});
//在此設置了一個12秒的等待時間,如果group的執行結束沒有到12秒那么就返回0
//如果執行group的執行時間超過了12秒,那么返回非0 數值,
//在使用dispatch_group_wait函數的時候,會阻塞當前線程,阻塞的時間 在wait函數時間值和當前group執行時間值取最小的。
long kk=dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 12 * NSEC_PER_SEC));
if(kk==0)
{
NSLog(@"dispatch_group_wait 結果1");
}
else
{
NSLog(@"dispatch_group_wait 結果2");
}
}
執行結果
2016-07-21 13:56:47.471 GCD_Demo[9065:1165380] star
2016-07-21 13:56:48.472 GCD_Demo[9065:1165494] group_work_1
2016-07-21 13:56:49.476 GCD_Demo[9065:1165502] group_work_3
2016-07-21 13:56:53.475 GCD_Demo[9065:1165485] group_work_2
2016-07-21 13:56:53.475 GCD_Demo[9065:1165380] dispatch_group_wait 結果1
-
dispatch_group_enter&dispatch_group_leave
假如我們不想使用dispatch_group_async異步的將任務丟到group中去執行,這時候就需要用到dispatch_group_enter跟dispatch_group_leave方法,這兩個方法要配對出現,以下這兩種方法是等價的:
-(void)asyncGroupEnter
{
// 群組-統一監控一組任務
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 1> 入組 -> 之后的 block 會被 group 監聽
// dispatch_group_enter 一定和 dispatch_group_leave 要配對出現
dispatch_group_enter(group);
dispatch_async(queue, ^{
NSLog(@"dispatch_async_work1");
// block 的末尾,所有任務執行完畢后,添加一個出組
dispatch_group_leave(group);
});
// 再次入組
dispatch_group_enter(group);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:6];
NSLog(@"dispatch_async_work1");
// block 的末尾,所有任務執行完畢后,添加一個出組
dispatch_group_leave(group);
});
// 群組結束
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"OVER");
});
NSLog(@"come here");
}
執行結果
2016-07-21 15:21:40.707 GCD_Demo[9256:1205427] come here
2016-07-21 15:21:40.707 GCD_Demo[9256:1205465] dispatch_async_work1
2016-07-21 15:21:46.709 GCD_Demo[9256:1205460] dispatch_async_work1
2016-07-21 15:21:46.710 GCD_Demo[9256:1205427] OVER
6. Dispatch Block
添加到gcd隊列中執行的任務是以block的形式添加的,block封裝了需要執行功能,block帶來的開發效率提升就不說了,gcd跟block可以說是一對好基友,能夠很好的配合使用。
-(void)dispatchBlock
{
dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block=dispatch_block_create(0, ^{
NSLog(@"dispatchBlock_work");
});
dispatch_sync(queue, block);
}
** 1.dispatch_block_wait**
當需要等待前面的任務執行完畢時,我們可以使用dispatch_block_wait這個接口,設置等待時間DISPATCH_TIME_FOREVER會一直等待直到前面的任務完成.用法跟dispatch_group_wait類似
-(void)dispatchBlockWait
{
dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
dispatch_block_t block = dispatch_block_create(0, ^{
NSLog(@"before sleep");
[NSThread sleepForTimeInterval:6];
NSLog(@"after sleep");
});
dispatch_async(queue, block);
//等待前面的任務執行完畢
long kk=dispatch_block_wait(block, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC));
if(kk==0)
{
NSLog(@"coutinue");
}
else
{
NSLog(@"timeOut!!!");
}
}
執行結果
2016-07-21 16:28:38.313 GCD_Demo[9533:1251011] before sleep
2016-07-21 16:28:41.314 GCD_Demo[9533:1250971] timeOut!!!
2016-07-21 16:28:44.318 GCD_Demo[9533:1251011] after sleep
** 2.dispatch_block_notify**
dispatch_block_notify當觀察的某個block執行結束之后立刻通知提交另一特定的block到指定的queue中執行,該函數有三個參數,第一參數是需要觀察的block,第二個參數是被通知block提交執行的queue,第三參數是當需要被通知執行的block
-(void)dispatchBlockNotify
{
dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
dispatch_block_t previousBlock = dispatch_block_create(0, ^{
NSLog(@"previousBlock begin");
[NSThread sleepForTimeInterval:2];
NSLog(@"previousBlock done");
});
dispatch_async(queue, previousBlock);
dispatch_block_t notifyBlock = dispatch_block_create(0, ^{
NSLog(@"notifyBlock");
});
//當previousBlock執行完畢后,提交notifyBlock到global queue中執行
dispatch_block_notify(previousBlock, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), notifyBlock);
}
執行結果
2016-07-21 16:38:19.756 GCD_Demo[9664:1261328] previousBlock begin
2016-07-21 16:38:21.762 GCD_Demo[9664:1261328] previousBlock done
2016-07-21 16:38:21.762 GCD_Demo[9664:1261329] notifyBlock
3. dispatch_block_cancel
可以取消提交到隊列的block
-(void)dispatchBlockCancel
{
dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_block_t block1 = dispatch_block_create(0, ^{
NSLog(@"block1 begin");
[NSThread sleepForTimeInterval:1];
NSLog(@"block1 done");
});
dispatch_block_t block2 = dispatch_block_create(0, ^{
NSLog(@"block2 ");
});
dispatch_async(queue, block1);
dispatch_async(queue, block2);
dispatch_block_cancel(block2);
}
執行結果
2016-07-21 16:50:28.140 GCD_Demo[9723:1272259] block1 begin
2016-07-21 16:50:29.144 GCD_Demo[9723:1272259] block1 done
7.dispatch_after
來延遲執行的GCD方法,因為在主線程中我們不能用sleep來延遲方法的調用,所以用它是最合適的,我們做一個簡單的例子:
-(void)dispatchAfter
{
NSLog(@"dispatchAfter_star");
int64_t time=2*NSEC_PER_SEC;
dispatch_queue_t mainQueue=dispatch_get_main_queue();
for (int i=0; i<5; i++) {
dispatch_time_t disTime=dispatch_time(DISPATCH_TIME_NOW, time*i);
dispatch_after(disTime, mainQueue, ^{
NSLog(@"dispatchAfter_work");
});
}
}
執行結果
2016-07-21 16:12:07.204 GCD_Demo[9439:1237251] dispatchAfter_star
2016-07-21 16:12:07.211 GCD_Demo[9439:1237251] dispatchAfter_work
2016-07-21 16:12:09.398 GCD_Demo[9439:1237251] dispatchAfter_work
2016-07-21 16:12:11.205 GCD_Demo[9439:1237251] dispatchAfter_work
2016-07-21 16:12:13.205 GCD_Demo[9439:1237251] dispatchAfter_work
2016-07-21 16:12:15.205 GCD_Demo[9439:1237251] dispatchAfter_work
8.dispatch_apply
dispatch_apply類似一個for循環,會在指定的dispatch queue中運行block任務n次,如果隊列是并發隊列,則會并發執行block任務,dispatch_apply是一個同步調用,block任務執行n次后才返回。
-(void)dispatchApply
{
dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_apply(6, queue, ^(size_t i) {
NSLog(@"do a job %zu times",i);
});
NSLog(@"go on");
}
執行結果
2016-07-21 17:04:54.558 GCD_Demo[9831:1284549] do a job 0 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284583] do a job 1 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284589] do a job 2 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284593] do a job 3 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284549] do a job 4 times
2016-07-21 17:04:54.564 GCD_Demo[9831:1284583] do a job 5 times
2016-07-21 17:04:54.566 GCD_Demo[9831:1284549] go on
9.dispatch_once
整個程序運行中只會執行一次,使用dispatch_once可以簡化代碼并且徹底保證線程安全,開發者根本無須擔心加鎖或者同步。所有問題都由GCD在底層處理。由于每次調用時都必須使用完全相同的標記,所以標記要聲明成static。所以用在單例模式上是最好的
static SingletonTimer * instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[SingletonTimer alloc] init];
});
return instance;
10. dispatch_barrier_async
dispatch_barrier_async用于等待前面的任務執行完畢后自己才執行,而它后面的任務需等待它完成之后才執行。一個典型的例子就是數據的讀寫,通常為了防止文件讀寫導致沖突,我們會創建一個串行的隊列,所有的文件操作都是通過這個隊列來執行,比如FMDB,這樣就可以避免讀寫沖突。不過其實這樣效率是有提升的空間的,當沒有更新數據時,讀操作其實是可以并行進行的,而寫操作需要串行的執行
-(void)diapatchBarrier
{
dispatch_queue_t queue = dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:6];
NSLog(@"dispatch_async_work1");
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async_work2");
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_async_work3");
[NSThread sleepForTimeInterval:1];
});
dispatch_async(queue, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async_work4");
});
}
執行結果
2016-07-21 15:54:24.402 GCD_Demo[9354:1225160] dispatch_async_work2
2016-07-21 15:54:28.403 GCD_Demo[9354:1225152] dispatch_async_work1
2016-07-21 15:54:28.403 GCD_Demo[9354:1225152] dispatch_async_work3
2016-07-21 15:54:30.412 GCD_Demo[9354:1225152] dispatch_async_work4
11.dispatch_set_target_queue
1.系統的Global Queue是可以指定優先級的,那我們可以用到dispatch_set_target_queue這個方法來指定自己創建隊列的優先級
-(void)DispatchSet
{
dispatch_queue_t serialDiapatchQueue=dispatch_queue_create("com.GCD_demo.www", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t dispatchgetglobalqueue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
dispatch_set_target_queue(serialDiapatchQueue, dispatchgetglobalqueue);
dispatch_async(serialDiapatchQueue, ^{
NSLog(@"我優先級低,先讓讓");
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"我優先級高,我先block");
});
}
執行結果
2016-07-21 17:22:02.512 GCD_Demo[9902:1297023] 我優先級高,我先block
2016-07-21 17:22:02.512 GCD_Demo[9902:1297035] 我優先級低,先讓讓
2.dispatch_set_target_queue除了能用來設置隊列的優先級之外,還能夠創建隊列的層次體系,當我們想讓不同隊列中的任務同步的執行時,我們可以創建一個串行隊列,然后將這些隊列的target指向新創建的隊列即可
-(void)dispatchSet2
{
dispatch_queue_t targetQueue = dispatch_queue_create("target_queue", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_queue_t queue2 = dispatch_queue_create("queue2", DISPATCH_QUEUE_CONCURRENT);
dispatch_set_target_queue(queue1, targetQueue);
dispatch_set_target_queue(queue2, targetQueue);
dispatch_async(queue1, ^{
[NSThread sleepForTimeInterval:3.f];
NSLog(@"do job1");
});
dispatch_async(queue2, ^{
[NSThread sleepForTimeInterval:2.f];
NSLog(@"do job2");
});
dispatch_async(queue2, ^{
[NSThread sleepForTimeInterval:1.f];
NSLog(@"do job3");
});
}
執行結果
2016-07-21 17:28:54.327 GCD_Demo[10043:1303853] do job1
2016-07-21 17:28:56.331 GCD_Demo[10043:1303853] do job2
2016-07-21 17:28:57.335 GCD_Demo[10043:1303853] do job3