在上一篇講解了iOS開發(fā)的三種多線程實現(xiàn)方式的特點和用法,在這一篇主要講解一下GCD的用法。
GCD(Grand Central Dispatch)又叫大中央調(diào)度,它對線程操作進行了封裝,加入了很多新的特性,內(nèi)部進行了效率優(yōu)化,提供了簡潔的C語言接口,使用更加簡單高效,也是蘋果公司推薦的方式。
特點:
- GCD 可用于多核的并行運算
- GCD 會自動利用更多的 CPU 內(nèi)核(比如雙核、四核)
- GCD 會自動管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程)
- 程序員只需要告訴 GCD 想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼
- 執(zhí)行任務(wù)有兩種方式:同步執(zhí)行(sync)和異步執(zhí)行(async)。兩者的主要區(qū)別是:是否等待隊列的任務(wù)執(zhí)行結(jié)束,以及是否具備開啟新線程的能力。
- 兩種隊列:串行隊列和并發(fā)隊列。兩者都符合 FIFO(先進先出)的原則。兩者的主要區(qū)別是:執(zhí)行順序不同,以及開啟線程數(shù)不同。
GCD隊列執(zhí)行區(qū)別

1、只有異步提交任務(wù)時才會開啟新線程,異步提交到串行隊列會開啟一個新線程,異步提交到并發(fā)隊列可能會開啟多個線程。
2、同步提交任務(wù)無論提交到并發(fā)隊列還是串行隊列,都不會開啟新線程,都會直接在當前線程依次同步執(zhí)行。
3、如果當前線程是主線程,那么不可在當前線程提交同步任務(wù),否則會造成線程死鎖而報錯。
1、串行隊列與并發(fā)隊列dispatch_queue_t;
創(chuàng)建隊列
- DISPATCH_QUEUE_SERIAL 表示串行隊列,隊列內(nèi)任務(wù)一個接一個的執(zhí)行,按照先進先出(FIFO)的順序執(zhí)行
- DISPATCH_QUEUE_CONCURRENT 表示并發(fā)隊列,隊列內(nèi)任務(wù)可同時并列執(zhí)行,任務(wù)之間不會相互等待,執(zhí)行順序不可預(yù)測
// 串行隊列的創(chuàng)建方法
dispatch_queue_t queueSerial = dispatch_queue_create("com.jzsec.GCDtest", DISPATCH_QUEUE_SERIAL);
// 并發(fā)隊列的創(chuàng)建方法
dispatch_queue_t queueCon = dispatch_queue_create("com.jzsec.GCDtest", DISPATCH_QUEUE_CONCURRENT);
獲取系統(tǒng)隊列
- 對于串行隊列,GCD 提供了的一種特殊的串行隊列:主隊列(Main Dispatch Queue)
- 對于并發(fā)隊列,GCD 默認提供了全局并發(fā)隊列(Global Dispatch Queue)
// 主隊列的獲取方法
dispatch_queue_t queueMain = dispatch_get_main_queue();
// 全局并發(fā)隊列的獲取方法
/*優(yōu)先級:
#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
*/
dispatch_queue_t queueGlobal = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2、同步dispatch_sync與異步dispatch_async派發(fā)任務(wù);
- 同步指阻塞當前線程,即要等添加的耗時任務(wù)塊block完成后,函數(shù)才能返回,后面的代碼才可以繼續(xù)執(zhí)行。
- 異步指將任務(wù)添加到隊列后函數(shù)立刻返回,后面的代碼不用等待添加的任務(wù)完成返回即可繼續(xù)執(zhí)行。異步提交無法確認任務(wù)的執(zhí)行順序。
dispatch_sync(queue, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
3、同步執(zhí)行 + 并發(fā)隊列
特點:在當前線程中執(zhí)行任務(wù),不會開啟新線程,執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)。所有任務(wù)都是在當前線程(主線程)中執(zhí)行的,沒有開啟新的線程(同步執(zhí)行不具備開啟新線程的能力)。
任務(wù)按順序執(zhí)行的。按順序執(zhí)行的原因:雖然并發(fā)隊列可以開啟多個線程,并且同時執(zhí)行多個任務(wù)。但是因為本身不能創(chuàng)建新線程,只有當前線程這一個線程(同步任務(wù)不具備開啟新線程的能力),所以也就不存在并發(fā)。而且當前線程只有等待當前隊列中正在執(zhí)行的任務(wù)執(zhí)行完畢之后,才能繼續(xù)接著執(zhí)行下面的操作(同步任務(wù)需要等待隊列的任務(wù)執(zhí)行結(jié)束)。所以任務(wù)只能一個接一個按順序執(zhí)行,不能同時被執(zhí)行。
- (void)syncConcurrent {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"syncConcurrent---begin");
dispatch_queue_t queue = dispatch_queue_create("com.jzsec.GCDtest", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(queue, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_sync(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_sync(queue, ^{
// 追加任務(wù)3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
});
NSLog(@"syncConcurrent---end");
}
4、異步執(zhí)行 + 并發(fā)隊列
特點:可以開啟多個線程,任務(wù)交替(同時)執(zhí)行。
除了當前線程(主線程),系統(tǒng)又開啟了3個線程,并且任務(wù)是交替/同時執(zhí)行的。(異步執(zhí)行具備開啟新線程的能力。且并發(fā)隊列可開啟多個線程,同時執(zhí)行多個任務(wù))。
當前線程沒有等待,而是直接開啟了新線程,在新線程中執(zhí)行任務(wù)(異步執(zhí)行不做等待,可以繼續(xù)執(zhí)行任務(wù))。
- (void)asyncConcurrent {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"asyncConcurrent---begin");
dispatch_queue_t queue = dispatch_queue_create("com.jzsec.GCDtest", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
});
NSLog(@"asyncConcurrent---end");
}
5、同步執(zhí)行 + 串行隊列
特點:不會開啟新線程,在當前線程執(zhí)行任務(wù)。任務(wù)是串行的,執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)。
所有任務(wù)都是在當前線程(主線程)中執(zhí)行的,并沒有開啟新的線程(同步執(zhí)行不具備開啟新線程的能力)。任務(wù)是按順序執(zhí)行的(串行隊列每次只有一個任務(wù)被執(zhí)行,任務(wù)一個接一個按順序執(zhí)行)。
- (void)syncSerial {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"syncSerial---begin");
dispatch_queue_t queue = dispatch_queue_create("com.jzsec.GCDtest", DISPATCH_QUEUE_SERIAL);
dispatch_sync(queue, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_sync(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_sync(queue, ^{
// 追加任務(wù)3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
});
NSLog(@"syncSerial---end");
}
6、異步執(zhí)行 + 串行隊列
特點:會開啟新線程,但是因為任務(wù)是串行的,執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)。
開啟了一條新線程(異步執(zhí)行具備開啟新線程的能力,串行隊列只開啟一個線程)。任務(wù)是按順序執(zhí)行的(串行隊列每次只有一個任務(wù)被執(zhí)行,任務(wù)一個接一個按順序執(zhí)行)。
- (void)asyncSerial {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"asyncSerial---begin");
dispatch_queue_t queue = dispatch_queue_create("com.jzsec.GCDtest", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
});
NSLog(@"asyncSerial---end");
}
7、同步執(zhí)行 + 主隊列
特點(主線程調(diào)用):互等卡主不執(zhí)行。
特點(其他線程調(diào)用):不會開啟新線程,執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)。
- (void)syncMain {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"syncMain---begin");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_sync(queue, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_sync(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_sync(queue, ^{
// 追加任務(wù)3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
});
NSLog(@"syncMain---end");
}
8、異步執(zhí)行 + 主隊列
特點:只在主線程中執(zhí)行任務(wù),執(zhí)行完一個任務(wù),再執(zhí)行下一個任務(wù)
所有任務(wù)都是在當前線程(主線程)中執(zhí)行的,并沒有開啟新的線程(雖然異步執(zhí)行具備開啟線程的能力,但因為是主隊列,所以所有任務(wù)都在主線程中)。任務(wù)是按順序執(zhí)行的(因為主隊列是串行隊列,每次只有一個任務(wù)被執(zhí)行,任務(wù)一個接一個按順序執(zhí)行)。
- (void)asyncMain {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"asyncMain---begin");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
});
NSLog(@"asyncMain---end");
}
9、線程間通信
在其他線程完成了耗時操作時,回到主線程
- (void)communication {
// 獲取全局并發(fā)隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 獲取主隊列
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(queue, ^{
// 異步追加任務(wù)
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
// 回到主線程
dispatch_async(mainQueue, ^{
// 追加在主線程中執(zhí)行的任務(wù)
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
});
});
}
10、柵欄方法 dispatch_barrier_async
在執(zhí)行完柵欄前面的操作之后,才執(zhí)行柵欄操作,最后再執(zhí)行柵欄后邊的操作。
- (void)barrier {
dispatch_queue_t queue = dispatch_queue_create("com.jzsec.GCDtest", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_barrier_async(queue, ^{
// 追加任務(wù) barrier
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"barrier---%@",[NSThread currentThread]);// 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)3
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_async(queue, ^{
// 追加任務(wù)4
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"4---%@",[NSThread currentThread]); // 打印當前線程
}
});
}
11、延時執(zhí)行方法 dispatch_after
dispatch_after函數(shù)并不是在指定時間之后才開始執(zhí)行處理,而是在指定時間之后將任務(wù)追加到主隊列中。嚴格來說,這個時間并不是絕對準確的,但想要大致延遲執(zhí)行任務(wù),dispatch_after函數(shù)是很有效的。
- (void)after {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"asyncMain---begin");
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 2.0秒后異步追加任務(wù)代碼到主隊列,并開始執(zhí)行
NSLog(@"after---%@",[NSThread currentThread]); // 打印當前線程
});
}
12、一次性代碼(只執(zhí)行一次)dispatch_once
能保證某段代碼在程序運行過程中只被執(zhí)行1次,并且即使在多線程的環(huán)境下,dispatch_once也可以保證線程安全。
- (void)once {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 只執(zhí)行1次的代碼(這里面默認是線程安全的)
NSLog(@"dispatch_once");
});
}
13、快速迭代方法 dispatch_apply
按照指定的次數(shù)將指定的任務(wù)追加到指定的隊列中,并等待全部隊列執(zhí)行結(jié)束才繼續(xù)執(zhí)行。
- (void)apply {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSLog(@"apply---begin");
dispatch_apply(6, queue, ^(size_t index) {
NSLog(@"%zd---%@",index, [NSThread currentThread]);
});
NSLog(@"apply---end");
}
14、隊列組 dispatch_group_notify
當group所有任務(wù)都執(zhí)行完成之后,才執(zhí)行dispatch_group_notify block 中的任務(wù)。
- (void)groupNotify {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"group---begin");
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的異步任務(wù)1、任務(wù)2都執(zhí)行完畢后,回到主線程執(zhí)行下邊任務(wù)
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
NSLog(@"group---end");
});
}
15、隊列組 dispatch_group_wait
當所有任務(wù)執(zhí)行完成之后,才執(zhí)行 dispatch_group_wait 之后的操作。但是,使用dispatch_group_wait 會阻塞當前線程。
- (void)groupWait {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"group---begin");
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
});
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
});
// 等待上面的任務(wù)全部完成后,會往下繼續(xù)執(zhí)行(會阻塞當前線程)
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"group---end");
}
16、隊列組 dispatch_group_enter、dispatch_group_leave
- dispatch_group_enter 標志著一個任務(wù)追加到 group,執(zhí)行一次,相當于 group 中未執(zhí)行完畢任務(wù)數(shù)+1
- dispatch_group_leave 標志著一個任務(wù)離開了 group,執(zhí)行一次,相當于 group 中未執(zhí)行完畢任務(wù)數(shù)-1。
- 當 group 中未執(zhí)行完畢任務(wù)數(shù)為0的時候,才會使dispatch_group_wait解除阻塞,以及執(zhí)行追加到dispatch_group_notify中的任務(wù)。
- 當所有任務(wù)執(zhí)行完成之后,才執(zhí)行 dispatch_group_notify 中的任務(wù)。
- (void)groupEnterAndLeave
{
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
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, ^{
// 追加任務(wù)1
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
}
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(queue, ^{
// 追加任務(wù)2
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"2---%@",[NSThread currentThread]); // 打印當前線程
}
dispatch_group_leave(group);
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 等前面的異步操作都執(zhí)行完畢后,回到主線程.
for (int i = 0; i < 2; ++i) {
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"3---%@",[NSThread currentThread]); // 打印當前線程
}
NSLog(@"group---end");
});
NSLog(@"method---end");
}
17、semaphore 線程同步
- dispatch_semaphore_create:創(chuàng)建一個 Semaphore 并初始化信號的總量
- dispatch_semaphore_signal:發(fā)送一個信號,讓信號總量加 1
- dispatch_semaphore_wait:可以使總信號量減 1,信號總量小于 0 時就會一直等待(阻塞所在線程),否則就可以正常執(zhí)行。
- (void)semaphoreSync {
NSLog(@"currentThread---%@",[NSThread currentThread]); // 打印當前線程
NSLog(@"semaphore---begin");
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block int number = 0;
dispatch_async(queue, ^{
// 追加任務(wù)1
[NSThread sleepForTimeInterval:2]; // 模擬耗時操作
NSLog(@"1---%@",[NSThread currentThread]); // 打印當前線程
number = 100;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
NSLog(@"semaphore---end,number = %d",number);
}
參考:《iOS程序猿面試筆試寶典》
http://www.itdecent.cn/p/2d57c72016c6