1、GCD簡(jiǎn)介
Grand Central Dispatch (GCD),是蘋果推出的多線程解決方案,它主要用于優(yōu)化應(yīng)用程序以支持多核處理器以及其他對(duì)稱多處理系統(tǒng)。它是一個(gè)在線程池模式的基礎(chǔ)上執(zhí)行的并發(fā)任務(wù)。
2、任務(wù)和隊(duì)列
- 任務(wù):
就是執(zhí)行操作的意思,在GCD中使用 block 封裝。block就是一個(gè)提前準(zhǔn)備好的代碼塊,在需要的時(shí)候執(zhí)行 - 隊(duì)列:
- 串行隊(duì)列:一個(gè)接一個(gè)的調(diào)度任務(wù)
- 并發(fā)隊(duì)列:可以同時(shí)調(diào)度多個(gè)任務(wù)
- 主隊(duì)列: 專門用來在主線程上調(diào)度任務(wù)的"隊(duì)列"
主隊(duì)列不能在其他線程中調(diào)度任務(wù)!
如果主線程上當(dāng)前正在有執(zhí)行的任務(wù),主隊(duì)列暫時(shí)不會(huì)調(diào)度任務(wù)的執(zhí)行!
注意:主隊(duì)列不是主線程- 異步任務(wù),會(huì)在主線程的方法執(zhí)行完成后,被調(diào)度
- 同步任務(wù),會(huì)造成死鎖
- 全局隊(duì)列,系統(tǒng)提供給程序員,方便程序員使用的全局隊(duì)列
有關(guān)服務(wù)質(zhì)量問題,使用以下代碼能夠做到 iOS7 & iOS8 的適配
dispatch_get_global_queue(0, 0);
- 執(zhí)行任務(wù)的函數(shù)
- 同步執(zhí)行:當(dāng)前指令不完成,就不會(huì)執(zhí)行下一條指令
- 異步執(zhí)行:當(dāng)前指令不完成,同樣可以執(zhí)行下一條指令
異步是多線程的代名詞
- 小結(jié):
- 開不開線程,取決于執(zhí)行任務(wù)的函數(shù),同步不開,異步開
- 開幾條線程,取決于隊(duì)列,串行開一條,并發(fā)開多條(異步)
3、GCD的基本使用
GCD的基本使用步驟有兩步:
1、創(chuàng)建一個(gè)隊(duì)列。
2、將任務(wù)添加到隊(duì)列中,然后系統(tǒng)就會(huì)根據(jù)任務(wù)類型執(zhí)行任務(wù)。(同步執(zhí)行或異步執(zhí)行)
串形隊(duì)列+同步執(zhí)行
不會(huì)開線程,會(huì)順序執(zhí)行
// 1. 隊(duì)列
/**
參數(shù)
1. 隊(duì)列的名稱
2. 隊(duì)列的屬性
DISPATCH_QUEUE_SERIAL(NULL) 表示串行
*/
dispatch_queue_t q = dispatch_queue_create("com.chenhuan.queue", DISPATCH_QUEUE_SERIAL);
NSLog(@"start");
// 2. 執(zhí)行任務(wù)
for (int i = 0; i < 10; i++) {
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"end");
輸出結(jié)果
2017-07-29 19:08:27.030 Demo-GCD[942:62206] start
2017-07-29 19:08:27.030 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 0
2017-07-29 19:08:27.031 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 1
2017-07-29 19:08:27.031 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 2
2017-07-29 19:08:27.031 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 3
2017-07-29 19:08:27.031 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 4
2017-07-29 19:08:27.031 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 5
2017-07-29 19:08:27.032 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 6
2017-07-29 19:08:27.032 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 7
2017-07-29 19:08:27.032 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 8
2017-07-29 19:08:27.032 Demo-GCD[942:62206] <NSThread: 0x61800007eac0>{number = 1, name = main} 9
2017-07-29 19:08:27.032 Demo-GCD[942:62206] end
- 在
串行隊(duì)列 + 同步執(zhí)行可以看到,所有任務(wù)都是在主線程中執(zhí)行的,并沒有開啟新的線程。而且由于串行隊(duì)列,所以按順序一個(gè)一個(gè)執(zhí)行。 - 所有任務(wù)都在打印的
start和end之間,這說明任務(wù)是添加到隊(duì)列中馬上執(zhí)行的。
串形隊(duì)列+異步執(zhí)行
會(huì)開啟新的線程,一個(gè)一個(gè)順序執(zhí)行
dispatch_queue_t q = dispatch_queue_create("com.chenhuan.queue", NULL);
NSLog(@"start");
for (int i = 0; i<10; i++) {
dispatch_async(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"end");
輸出結(jié)果
2017-07-29 19:40:35.466 08-GCD演練[988:72561] start
2017-07-29 19:40:35.466 08-GCD演練[988:72561] end
2017-07-29 19:40:35.466 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 0
2017-07-29 19:40:35.467 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 1
2017-07-29 19:40:35.467 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 2
2017-07-29 19:40:35.467 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 3
2017-07-29 19:40:35.467 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 4
2017-07-29 19:40:35.467 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 5
2017-07-29 19:40:35.468 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 6
2017-07-29 19:40:35.468 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 7
2017-07-29 19:40:35.468 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 8
2017-07-29 19:40:35.468 08-GCD演練[988:72613] <NSThread: 0x610000072b00>{number = 3, name = (null)} 9
- 在
串形隊(duì)列+異步執(zhí)行可以看到,會(huì)開啟一條新的線程,并且一個(gè)一個(gè)執(zhí)行 - 所有任務(wù)是在打印的
start和end之后才開始執(zhí)行的。說明任務(wù)不是馬上執(zhí)行,而是將所有任務(wù)添加到隊(duì)列之后才開始同步執(zhí)行。
并發(fā)隊(duì)列+同步執(zhí)行
不會(huì)開啟線程,并且順序執(zhí)行
// 1. 隊(duì)列
dispatch_queue_t q = dispatch_queue_create("com.chenhuan.queue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"start");
// 2. 異步執(zhí)行
for (int i = 0; i<10; i++) {
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"end");
輸出結(jié)果
2017-07-29 20:38:10.211 Demo-GCD[1125:109556] start
2017-07-29 20:38:10.212 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 0
2017-07-29 20:38:10.212 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 1
2017-07-29 20:38:10.212 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 2
2017-07-29 20:38:10.212 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 3
2017-07-29 20:38:10.213 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 4
2017-07-29 20:38:10.213 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 5
2017-07-29 20:38:10.213 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 6
2017-07-29 20:38:10.213 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 7
2017-07-29 20:38:10.213 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 8
2017-07-29 20:38:10.214 Demo-GCD[1125:109556] <NSThread: 0x60800007a9c0>{number = 1, name = main} 9
2017-07-29 20:38:10.214 Demo-GCD[1125:109556] end
- 在
并發(fā)隊(duì)列 + 同步執(zhí)行可以看到,所有任務(wù)都是在主線程中執(zhí)行的,并沒有開啟新的線程。而且都是按順序一個(gè)一個(gè)執(zhí)行。 - 所有任務(wù)都在打印的
start和end之間,這說明任務(wù)是添加到隊(duì)列中馬上執(zhí)行的。
并發(fā)隊(duì)列+異步執(zhí)行
會(huì)開啟多條線程,并且交替執(zhí)行
// 1. 隊(duì)列
dispatch_queue_t q = dispatch_queue_create("com.chenhuan.queue", DISPATCH_QUEUE_CONCURRENT);
NSLog(@"start");
// 2. 異步執(zhí)行
for (int i = 0; i<10; i++) {
dispatch_async(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"end");
輸出結(jié)果
2017-07-29 20:36:52.573 Demo-GCD[1100:104147] start
2017-07-29 20:36:52.573 Demo-GCD[1100:104147] end
2017-07-29 20:36:52.573 Demo-GCD[1100:107782] <NSThread: 0x610000264e00>{number = 20, name = (null)} 0
2017-07-29 20:36:52.573 Demo-GCD[1100:108095] <NSThread: 0x618000262b40>{number = 39, name = (null)} 1
2017-07-29 20:36:52.574 Demo-GCD[1100:108096] <NSThread: 0x610000264f40>{number = 40, name = (null)} 2
2017-07-29 20:36:52.574 Demo-GCD[1100:108097] <NSThread: 0x60800026a200>{number = 41, name = (null)} 3
2017-07-29 20:36:52.574 Demo-GCD[1100:108099] <NSThread: 0x60800026a300>{number = 42, name = (null)} 4
2017-07-29 20:36:52.574 Demo-GCD[1100:108102] <NSThread: 0x610000266c40>{number = 43, name = (null)} 5
2017-07-29 20:36:52.574 Demo-GCD[1100:108100] <NSThread: 0x600000264d80>{number = 45, name = (null)} 7
2017-07-29 20:36:52.574 Demo-GCD[1100:108104] <NSThread: 0x600000264c00>{number = 44, name = (null)} 6
2017-07-29 20:36:52.574 Demo-GCD[1100:108106] <NSThread: 0x60800026a280>{number = 46, name = (null)} 8
2017-07-29 20:36:52.574 Demo-GCD[1100:108107] <NSThread: 0x60800026a2c0>{number = 47, name = (null)} 9
- 在
并發(fā)隊(duì)列 + 異步執(zhí)行可以看到,所有任務(wù)都是在異步線程中執(zhí)行。并且任務(wù)是交替著同時(shí)執(zhí)行的。 - 所有任務(wù)都在打印的
start和end之間,這說明任務(wù)是添加到隊(duì)列中馬上執(zhí)行的。
主隊(duì)列+同步執(zhí)行
不要這樣干,會(huì)造成死鎖
dispatch_queue_t q = dispatch_get_main_queue();
NSLog(@"卡死了嗎?");
dispatch_sync(q, ^{
NSLog(@"我來了");
});
NSLog(@"come here");
輸出結(jié)果
2017-07-29 21:13:23.550 Demo-GCD[1148:120053] 卡死了嗎?
- 如果你自己運(yùn)行以上代碼,會(huì)發(fā)現(xiàn)程序不能運(yùn)行了。這是因?yàn)檎粘闪怂梨i
- 我們知道
dispatch_sync表示同步的執(zhí)行任務(wù),也就是說執(zhí)行dispatch_sync后,當(dāng)前隊(duì)列會(huì)阻塞。而dispatch_sync中的block如果要在當(dāng)前隊(duì)列中執(zhí)行,就得等待當(dāng)前隊(duì)列程執(zhí)行完成。 - 在上面這個(gè)例子中,主隊(duì)列在執(zhí)行
dispatch_sync,隨后隊(duì)列中新增一個(gè)任務(wù)block。因?yàn)橹麝?duì)列是同步隊(duì)列,所以block要等dispatch_sync執(zhí)行完才能執(zhí)行,但是dispatch_sync是同步派發(fā),要等block執(zhí)行完才算是結(jié)束。在主隊(duì)列中的兩個(gè)任務(wù)互相等待,導(dǎo)致了死鎖。
主隊(duì)列+異步執(zhí)行
// 1. 主隊(duì)列 - 程序啟動(dòng)之后已經(jīng)存在主線程,主隊(duì)列同樣存在
dispatch_queue_t q = dispatch_get_main_queue();
// 2. 安排一個(gè)任務(wù)
for (int i = 0; i<10; i++) {
dispatch_async(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"睡會(huì)");
[NSThread sleepForTimeInterval:2.0];
NSLog(@"come here");
輸出結(jié)果
2017-07-29 21:21:30.547 Demo-GCD[1208:127513] 睡會(huì)
2017-07-29 21:21:32.548 Demo-GCD[1208:127513] come here
2017-07-29 21:21:32.548 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 0
2017-07-29 21:21:32.548 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 1
2017-07-29 21:21:32.549 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 2
2017-07-29 21:21:32.549 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 3
2017-07-29 21:21:32.549 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 4
2017-07-29 21:21:32.550 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 5
2017-07-29 21:21:32.550 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 6
2017-07-29 21:21:32.550 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 7
2017-07-29 21:21:32.550 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 8
2017-07-29 21:21:32.551 Demo-GCD[1208:127513] <NSThread: 0x600000076d40>{number = 1, name = main} 9
- 不開線程,順序執(zhí)行
- 從上面可以看出,異步執(zhí)行不會(huì)阻塞線程
全局隊(duì)列
/**
參數(shù)
1. 涉及到系統(tǒng)適配
iOS 8 服務(wù)質(zhì)量(讓線程響應(yīng)的更快還是更慢)
- QOS_CLASS_USER_INTERACTIVE 用戶交互(用戶迫切希望線程快點(diǎn)被執(zhí)行,不要用耗時(shí)的操作)
- QOS_CLASS_USER_INITIATED 用戶需要的(同樣不要使用耗時(shí)操作)
- QOS_CLASS_DEFAULT 默認(rèn)的(給系統(tǒng)用來重置隊(duì)列的)
** QOS_CLASS_UTILITY 實(shí)用工具(用來做耗時(shí)操作)
- QOS_CLASS_BACKGROUND 后臺(tái)
- QOS_CLASS_UNSPECIFIED 沒有指定優(yōu)先級(jí)
iOS 7 調(diào)度的優(yōu)先級(jí)
- DISPATCH_QUEUE_PRIORITY_HIGH 2 高優(yōu)先級(jí)
- DISPATCH_QUEUE_PRIORITY_DEFAULT 0 默認(rèn)優(yōu)先級(jí)
- DISPATCH_QUEUE_PRIORITY_LOW (-2) 低優(yōu)先級(jí)
- DISPATCH_QUEUE_PRIORITY_BACKGROUND 后臺(tái)優(yōu)先級(jí)
提示:尤其不要選擇 BACKGROUND 優(yōu)先級(jí)和服務(wù)質(zhì)量,用戶不需要知道線程什么時(shí)候執(zhí)行完成!線程的執(zhí)行會(huì)慢的令人發(fā)指!
有關(guān)服務(wù)質(zhì)量的介紹,用在與 XPC 框架結(jié)合使用的,XPC 用在 MAC 平臺(tái)上做進(jìn)程間通訊的框架!
因?yàn)榇蠹夜ぷ骱?,暫時(shí)會(huì)考慮 iOS7 & iOS8 的適配,無法使用服務(wù)質(zhì)量,直接指定 0,能夠做到 iOS7 & 8 的適配
dispatch_get_global_queue(0, 0);
2. 為未來使用保留的,應(yīng)該始終傳入0
*/
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
for (int i = 0; i < 10; i++) {
dispatch_async(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
NSLog(@"com here");
- 全局隊(duì)列可以當(dāng)作并發(fā)隊(duì)列來使用。一般我們?cè)陂_發(fā)過程中都是使用
global_queue
4、GCD的其他一些用法
dispatch_group
在實(shí)際開發(fā)中,有的時(shí)候,會(huì)需要同時(shí)監(jiān)聽多個(gè)異步任務(wù)最終完成的情況!這個(gè)時(shí)候就需要用到我們的 dispatch_group
// 1. 隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
// 2. 調(diào)度組
dispatch_group_t group = dispatch_group_create();
// 3. 添加任務(wù),讓隊(duì)列調(diào)度,指定任務(wù)執(zhí)行函數(shù),最終通知群組
dispatch_group_async(group, queue, ^{
NSLog(@"download A %@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"download B %@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:0.8];
NSLog(@"download C %@", [NSThread currentThread]);
});
// 4. 所有任務(wù)執(zhí)行完畢后,獲得通知
// 用一個(gè)調(diào)度組,可以監(jiān)聽全局隊(duì)列調(diào)度的任務(wù),執(zhí)行完畢后,在主隊(duì)列執(zhí)行最終處理!
// dispatch_group_notify 本身是異步的
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// 更新UI,通知用戶!
NSLog(@"OK %@", [NSThread currentThread]);
});
NSLog(@"come here");
輸出結(jié)果
2017-07-29 21:31:18.362 Demo-GCD[1255:135674] come here
2017-07-29 21:31:18.362 Demo-GCD[1255:135726] download A <NSThread: 0x60000006e040>{number = 3, name = (null)}
2017-07-29 21:31:19.166 Demo-GCD[1255:135723] download C <NSThread: 0x60000006b200>{number = 4, name = (null)}
2017-07-29 21:31:19.362 Demo-GCD[1255:135741] download B <NSThread: 0x60000006fd80>{number = 5, name = (null)}
2017-07-29 21:31:19.363 Demo-GCD[1255:135674] OK <NSThread: 0x60800006c540>{number = 1, name = main}
首先我們要通過 dispatch_group_create() 方法生成一個(gè)組。
接下來,我們把 dispatch_async 方法換成 dispatch_group_async。這個(gè)方法多了一個(gè)參數(shù),第一個(gè)參數(shù)填剛剛創(chuàng)建的分組。
最后調(diào)用 dispatch_group_notify 方法。這個(gè)方法表示把第三個(gè)參數(shù) block 傳入第二個(gè)參數(shù)隊(duì)列中去。而且可以保證第三個(gè)參數(shù) block 執(zhí)行時(shí),group 中的所有任務(wù)已經(jīng)全部完成。
dispatch_group 第二種調(diào)用方式
// 1. 隊(duì)列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 2. 調(diào)度組
dispatch_group_t g = dispatch_group_create();
// 3. 進(jìn)入群組,執(zhí)行此函數(shù)后,再添加的異步執(zhí)行的block,會(huì)被group監(jiān)聽
// dispatch_group_enter & dispatch_group_leave一定要配對(duì)出現(xiàn)
dispatch_group_enter(g);
// 4. 添加任務(wù)
dispatch_async(q, ^{
[NSThread sleepForTimeInterval:10.0];
NSLog(@"download A");
// 異步任務(wù)中,所有的代碼執(zhí)行完畢后,最后離開群組
dispatch_group_leave(g);
});
// 再次添加任務(wù)
dispatch_group_enter(g);
// 5. 添加任務(wù) B
dispatch_async(q, ^{
NSLog(@"download B");
// 異步任務(wù)中,所有的代碼執(zhí)行完畢后,最后離開群組
dispatch_group_leave(g);
});
// 6. 攔截通知
// dispatch_group_notify(g, q, ^{
// NSLog(@"Over");
// });
// 等待到永遠(yuǎn),死等,阻塞住線程執(zhí)行,一直到所有的任務(wù)執(zhí)行完畢,才會(huì)執(zhí)行后續(xù)的代碼!
long time = dispatch_group_wait(g, dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)));
NSLog(@"result=%ld",time);
NSLog(@"come here");
輸出結(jié)果
2017-07-29 21:52:08.123 Demo-GCD[1326:154377] download B
2017-07-29 21:52:10.124 Demo-GCD[1326:154323] result=49
2017-07-29 21:52:10.124 Demo-GCD[1326:154323] come here
2017-07-29 21:52:18.126 Demo-GCD[1326:154391] download A
dispatch_group_wait 方法是一個(gè)很有用的方法,它的完整定義如下:
long dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
第一個(gè)參數(shù)表示要等待的 group,第二個(gè)則表示等待時(shí)間。返回值表示經(jīng)過指定的等待時(shí)間,屬于這個(gè) group 的任務(wù)是否已經(jīng)全部執(zhí)行完,如果是則返回 0,否則返回非 0。
第二個(gè) dispatch_time_t 類型的參數(shù)還有兩個(gè)特殊值:DISPATCH_TIME_NOW 和 DISPATCH_TIME_FOREVER。
前者表示立刻檢查屬于這個(gè) group 的任務(wù)是否已經(jīng)完成,后者則表示一直等到屬于這個(gè) group 的任務(wù)全部完成。
dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC))傳入這個(gè)參數(shù)表示等待兩秒后檢查執(zhí)行情況。顯然沒有執(zhí)行完成 result=49。
dispatch_after
通過 GCD 還可以進(jìn)行簡(jiǎn)單的定時(shí)操作,比如在 3 秒后執(zhí)行某個(gè) block 。代碼如下:
NSLog(@"come here");
/**
參數(shù):
從現(xiàn)在開始,經(jīng)過多少納秒之后,讓 queue 隊(duì)列,調(diào)度 block 任務(wù),異步執(zhí)行!
1. when
2. queue
3. block
// 從現(xiàn)在開始,經(jīng)過多少納秒之后
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC));
// 主隊(duì)列
// dispatch_after(when, dispatch_get_main_queue(), ^{
// NSLog(@"%@", [NSThread currentThread]);
// });
// 全局隊(duì)列
// dispatch_after(when, dispatch_get_global_queue(0, 0), ^{
// NSLog(@"%@", [NSThread currentThread]);
// });
// 串行隊(duì)列
dispatch_after(when, dispatch_queue_create("com.chenhuan.queue", NULL), ^{
NSLog(@"%@", [NSThread currentThread]);
});
dispatch_after 方法有三個(gè)參數(shù)。第一個(gè)表示時(shí)間,也就是從現(xiàn)在起往后三秒鐘。第二、三個(gè)參數(shù)分別表示要提交的任務(wù)和提交到哪個(gè)隊(duì)列。
dispatch_once
dispathc_once 函數(shù)可以確保某個(gè) block 在應(yīng)用程序執(zhí)行的過程中只被處理一次,而且它是線程安全的。所以單例模式可以很簡(jiǎn)單的實(shí)現(xiàn),以 OC 中單例類為例
+ (instancetype)sharedInstance {
static id instance = nil;
static dispatch_once_t once;
dispatch_once($once, ^{
instance = [[self alloc] init];
});
return sharedManagerInstance;
}