本篇是關于GCD的一些函數的
1.dispatch_after
- 準確含義是在指定時間后,將任務追加到隊列中。
- dispatch_after是一個異步函數。
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3ull * NSEC_PER_SEC);
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"waited at least three seconds");
});
2.dispatch_once
dispatch_once() 以線程安全的方式執行且僅執行其代碼塊一次。通常用來生成單例。
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// 初始化單例
});
3.dispatch_group
用于當多個任務完成時候通知你。這些任務可以是同步的,也可以是異步的。
當組里的任務全部完成時,可以同步dispatch_group_wait 或者異步的dispatch_group_notify通知你。
1.dispatch_group_wait
- (void)downloadPhotosWithCompletionBlock:(CompleteBlock)completionBlock{
dispatch_async(dispatch_get_global_queue(0, 0), ^{ // 1
dispatch_group_t downloadGroup = dispatch_group_create(); // 2
for (NSInteger i = 0; i < 3; i++) {
dispatch_group_enter(downloadGroup); // 3
NSString *url = self.photoURLs[i];
[LoadingEngine loadWithURL:url
completionBlock:^(UIImage *image, NSError *_error) {
[self.photoArr addObject:image];
dispatch_group_leave(downloadGroup); // 4
}];
}
dispatch_group_wait(downloadGroup, DISPATCH_TIME_FOREVER); // 5
dispatch_async(dispatch_get_main_queue(), ^{ // 6
if (completionBlock) { // 7
completionBlock(self.photoArr);
}
});
});
}
- dispatch_group_wait 會阻塞當前線程。所以要用 dispatch_async 將整個方法放入后臺隊列以避免阻塞主線程。
2.第二種方式:dispatch_group_notify
- (void)downloadPhotosWithCompletionBlock:(CompleteBlock)completionBlock{
dispatch_group_t downloadGroup = dispatch_group_create(); // 2
for (NSInteger i = 0; i < 3; i++) {
dispatch_group_enter(downloadGroup); // 3
NSString *url = self.photoURLs[i];
[LoadingEngine loadWithURL:url
completionBlock:^(UIImage *image, NSError *_error) {
[self.photoArr addObject:image];
dispatch_group_leave(downloadGroup); // 4
}];
}
dispatch_group_notify(downloadGroup, dispatch_get_main_queue(), ^{
if (completionBlock) { // 7
completionBlock(self.photoArr);
}
});
}
- dispatch_group_notify是異步的,當group中的任務都完成了,notify會執行代碼。
4.dispatch_semaphore 信號量
Dispatch Semaphore是持有技術的信號。讓你控制多個消費者對有限數量資源的訪問。
臨界區:就是一段代碼不能被并發執行,也就是,兩個線程不能同時執行這段代碼。
1.相關函數
// 創建并設置信號量
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
//同步函數:如果信號量大于等于1,則減1,并返回。 如果信號量為0則阻塞當前線程。
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 信號量加1
dispatch_semaphore_signal(semaphore);
用法1:創建臨界區
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
臨界區
dispatch_semaphore_signal(semaphore);
- 這種用法在SDWebimage中大量使用。
用法2:將異步方法進行同步
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// 異步方法
[LoadingEngine loadWithURL:url
completionBlock:^(UIImage *image, NSError *_error) {
[self.photoArr addObject:image];
dispatch_semaphore_signal(semaphore);
}];
dispatch_semaphore_wait(semaphore,time);// 阻塞當前線程直到異步方法返回。
5.dispatch_suspend / dispatch_resume
dispatch_suspend(queue)函數掛起指定的queue,dispatch_resuem(queue)函數恢復指定的queue。
這兩個函數對已經執行的任務沒有影響。 掛起后,追加到queue中但是未執行的任務停止執行,恢復使這些任務能夠繼續執行。
6.其他GCD函數
dispatch_ barriers 是一組函數,在并發隊列上工作時扮演一個串行式的瓶頸。使用 GCD 的障礙(barrier)API 確保提交的 Block 在那個特定時間上是指定隊列上唯一被執行的條目。
dispatch_apply 函數按照指定的次數,將指定的block追加到指定的Dispatch Queue中。 并等待全部處理執行結束。