GCD
概念: 將任務(wù)添加到隊(duì)列中, 并且指定執(zhí)行任務(wù)的函數(shù);
- 任務(wù)使用block封裝, 沒(méi)有參數(shù), 沒(méi)有返回值
- 執(zhí)行任務(wù)的函數(shù):
同步 dispatch_sync :
必須等待當(dāng)前語(yǔ)句執(zhí)行完畢,才會(huì)執(zhí)行下一條語(yǔ)句;
不會(huì)開(kāi)啟線程;
在當(dāng)前的block執(zhí)行任務(wù).
異步 dispathc_asyc:
不必等待當(dāng)前語(yǔ)句執(zhí)行完畢, 就可以一執(zhí)行下一條語(yǔ)句;
會(huì)開(kāi)啟線程執(zhí)行block中的任務(wù);
異步是對(duì)線程的代名詞. - 隊(duì)列-負(fù)責(zé)調(diào)度任務(wù):
串行隊(duì)列: dispatch_queue_create("jianshu", NULL);
一次只能調(diào)度一個(gè)任務(wù)
并發(fā)隊(duì)列: dispatch_queue_create("itheima", DISPATCH_QUEUE_CONCURRENT);
一次可以調(diào)度對(duì)個(gè)任務(wù)
主隊(duì)列: dispatch_get_main_queue();
專門在主線程調(diào)度任務(wù)的隊(duì)列
不會(huì)開(kāi)啟線程
在主線程空閑的時(shí)候才會(huì)調(diào)度任務(wù)在主線程執(zhí)行
總結(jié):
- 開(kāi)不開(kāi)線程是由執(zhí)行任務(wù)的函數(shù)決定的:
同步不開(kāi)線程;
異步開(kāi)線程. - 開(kāi)幾條線程是由隊(duì)列決定的:
串行隊(duì)列開(kāi)一條;
并發(fā)隊(duì)列開(kāi)多條線程, 具體數(shù)量由底層線程池決定;
全局隊(duì)列:
是系統(tǒng)為了方便程序員開(kāi)發(fā)提供的, 與并發(fā)隊(duì)列效果一直, 但也有區(qū)別:
- 全局隊(duì)列: 沒(méi)有名稱, 無(wú)論MRC或者ARC都不需要考慮釋放, 日常開(kāi)發(fā)建議使用全局隊(duì)列.
- 并發(fā)隊(duì)列:
- 有名稱, 和NSThread的name屬性類似;
- 如果在 MRC 開(kāi)發(fā)時(shí),需要使用 dispatch_release(q); 釋放相應(yīng)的對(duì)象
- dispatch_barrier 必須使用自定義的并發(fā)隊(duì)列
- 開(kāi)發(fā)第三方框架時(shí),建議使用并發(fā)隊(duì)列
延遲操作:
dispatch_after(dispatch_time_t when, dispatch_queue_t _Nonnull queue, ^(void)block)
- (void)delay {
/**
從現(xiàn)在開(kāi)始,經(jīng)過(guò)多少納秒,由"隊(duì)列"調(diào)度異步執(zhí)行 block 中的代碼
參數(shù)
1. when 從現(xiàn)在開(kāi)始,經(jīng)過(guò)多少納秒
2. queue 隊(duì)列
3. block 異步執(zhí)行的任務(wù)
*/
dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC));
void (^task)() = ^ {
NSLog(@"%@", [NSThread currentThread]);
};
// 主隊(duì)列
// dispatch_after(when, dispatch_get_main_queue(), task);
// 全局隊(duì)列
// dispatch_after(when, dispatch_get_global_queue(0, 0), task);
// 串行隊(duì)列
dispatch_after(when, dispatch_queue_create("itheima", NULL), task);
NSLog(@"come here");
}
一次執(zhí)行:
有的時(shí)候,在程序開(kāi)發(fā)中,有些代碼只想從程序啟動(dòng)就只執(zhí)行一次,典型的應(yīng)用場(chǎng)景就是“單例”
- (void)once{
NSLog(@"來(lái)了");
//蘋(píng)果提供的一次執(zhí)行機(jī)制, 不僅執(zhí)行一次, 而且線程安全
static dispatch_once_t onceToken;
NSLog(@"%ld",onceToken);
//蘋(píng)果推薦使用GCD 一次執(zhí)行, 效率高, 不要使用互斥鎖, 效率低
dispatch_once(&onceToken, ^{
NSLog(@"執(zhí)行了%@", [NSThread currentThread]);
});
}
- (void)testOnce
{
for (int i = 0; i< 10; i++) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[self once];
});
}
}
調(diào)度組:
常規(guī)使用:
- (void)group1 {
// 1. 調(diào)度組
dispatch_group_t group = dispatch_group_create();
// 2. 隊(duì)列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// 3. 將任務(wù)添加到隊(duì)列和調(diào)度組
dispatch_group_async(group, q, ^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"任務(wù) 1 %@", [NSThread currentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任務(wù) 2 %@", [NSThread currentThread]);
});
dispatch_group_async(group, q, ^{
NSLog(@"任務(wù) 3 %@", [NSThread currentThread]);
});
// 4. 監(jiān)聽(tīng)所有任務(wù)完成
dispatch_group_notify(group, q, ^{
NSLog(@"OVER %@", [NSThread currentThread]);
});
// 5. 判斷異步
NSLog(@"come here");
}
另一種寫(xiě)法:
// MARK: - 調(diào)度組 2
- (void)group2 {
// 1. 調(diào)度組
dispatch_group_t group = dispatch_group_create();
// 2. 隊(duì)列
dispatch_queue_t q = dispatch_get_global_queue(0, 0);
// dispatch_group_enter & dispatch_group_leave 必須成對(duì)出現(xiàn)
dispatch_group_enter(group);
dispatch_group_async(group, q, ^{
NSLog(@"任務(wù) 1 %@", [NSThread currentThread]);
// dispatch_group_leave 必須是 block 的最后一句
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_group_async(group, q, ^{
NSLog(@"任務(wù) 2 %@", [NSThread currentThread]);
// dispatch_group_leave 必須是 block 的最后一句
dispatch_group_leave(group);
});
// 4. 阻塞式等待調(diào)度組中所有任務(wù)執(zhí)行完畢
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
// 5. 判斷異步
NSLog(@"OVER %@", [NSThread currentThread]);
}