GCD
1、定義:
Grand Central Dispatch;
iOS的一種底層多線程機制;
多核編程的解決方法;
使用內聯的形式,將block代碼,放置其中;
GCD可以說是依賴於Block,瞭解:Block
2、控制:
dispatch_async(queue, block);
其中 queue 隊列,系統提供兩種,一種是串行隊列(SerialDispatchQueue),一種是並行隊列(ConcurrentDispatchQueue);
block 是其中的代碼塊,queue 隊列控制block的使用形式;
3、MainDispatchQueue:
將任務插入主線程的RunLoop當中去執行,是個串行隊列;
可以使用它來更新UI;
獲取主線程隊列:
dispatch_queue_t queue = dispatch_get_main_queue();
簡略的執行:
// 主線程執行:
dispatch_async(dispatch_get_main_queue(), ^{
// something
});
4、GlobalDispatchQueue:
是一個全局的並行隊列,有高、默認、低和後臺4個優先級;
可以併發地執行多個任務;
DISPATCH_QUEUE_PRIORITY_HIGHT、
DISPATCH_QUEUE_PRIORITY_DEFAULT、
DISPATCH_QUEUE_PRIORITY_LOW、
DISPATCH_QUEUE_PRIORITY_BACKGROUND、
獲取全局隊列:
dispatch queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0)
簡略的執行:(並行三個任務隊列)
// 後臺執行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
// something
});
// 後臺執行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
// something
});
// 後臺執行:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRORITY_DEFAULT, 0), ^{
// something
});
5、SerialDispatchQueue:
串行隊列;
用於按順序同步訪問,可創建任意數量的串行隊列,各個串行隊列之間是併發的。
線程池只提供一個線程用來執行任務,所以後一個任務必須等到前一個任務執行結束才能開始。
創建串行隊列:
dispatch_queue_t myQueue = dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL);
執行:
//串行隊列
dispatch_async(dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL), ^{
// do something
});
dispatch_async(dispatch_queue_create(queueName, DISPATCH_QUEUE_SERIAL), ^{
// do something
});
dispatch_async 可以去執行多個來驗證是否是串行的;
6、普遍用法:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 做一些耗時操作
dispatch_async(dispatch_get_main_queue(), ^{
// update UI
});
});
7、執行一次的隊列:
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_shareInstance = [[self alloc] init];
});
可以保證整個應用程序生命週期中某段代碼只被執行一次!
適用於:單利模式
8、延遲執行:
// 延遲2秒執行:
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
// code to be executed on the main queue after delay
});
9、多次執行:
執行某個代碼片段N次。
int n=5;
dispatch_apply(n, globalQ, ^(size_t index) {
// 執行5次
});
其中的隊列,
可以是串行,也可以是並行隊列;
10、組任務:
dispatch_group_async可以實現監聽一組任務是否完成,完成後得到通知執行其他的操作;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
});
dispatch_group_async(group, queue, ^{
});
dispatch_group_async(group, queue, ^{
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"main thread.");
});
並行三個任務處於一個組中,組中任務執行完成後通知;
11、併發安全性:
在併發執行時的數據讀取和寫入,需要考慮數據的安全性;
由於dispatch_get_global_queue 無法控制其中的隊列,那麼如何做呢?
dispatch_barrier_async
在前面的隊列執行完成之後,纔會繼續下面的隊列;
dispatch_queue_t queue = dispatch_queue_create("com.qb.queue.GCD", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
});
dispatch_async(queue, ^{
});
dispatch_barrier_async(queue, ^{
NSLog(@"dispatch_barrier_async");
});
dispatch_async(queue, ^{
});
12、優先級:
通過dispatch_set_target_queue函數可以設置一個dispatch queue的優先級;
或者指定一個dispatch source相應的事件處理提交到哪個queue上。
dispatch_queue_t currentQueue = dispatch_queue_create("com.qb.demo.GCD", DISPATCH_QUEUE_CONCURRENT);
dispatch_queue_t targetQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_set_target_queue(currentQueue, targetQueue);
13、最後:
在沒有使用GCD時,當app被按home鍵退出後,app僅有最多5秒鐘的時候做一些保存或清理資源的工作。
在使用GCD後,app最多有10分鐘的時間在後臺長久運行。
這個時間可以用來做清理本地緩存,發送統計數據等工作。
即:GCD的另一個用處是可以讓程序在後臺較長久的運行。
(摘自網上,待驗證)
- (void)applicationDidEnterBackground:(UIApplication *)application {
[self beingBackgroundUpdateTask];
}
- (void)beingBackgroundUpdateTask {
self.backgroundUpdateTask = [[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:^{
[self endBackgroundUpdateTask];
}];
}
- (void)endBackgroundUpdateTask {
}