Grand Central Dispatch 簡稱GCD,蘋果在Mac OS X 10.6 ,iOS 4平臺首次發(fā)布,后續(xù)平臺也可用。關于GCD的更多信息,參考官方文檔。
<br >
特性
- 基于隊列工作 dispatch queue,嚴格按照FIFO(first in first out)
- 平行排隊特定任務
- 利用任何可用核心資源(多核處理器)處理任務
- 任務:函數(shù)(function)、block
<br >
Functions by Task
Main dispatch queue
- 主線程 queue ,一般用來更新ui,串行地在主線程上執(zhí)行任務
- main thread 有系統(tǒng)自動創(chuàng)建,并會自動關聯(lián)上你的應用的主線程,若想在應用內(nèi)使用,可使用以下三種方式:
調(diào)用 dispatch_main
調(diào)用 UIApplicationMain(iOS)或者NSApplicationMain(OS X)
使用 CFRunLoopRef
Concurrent - Global dispatch queue
- 并行隊列,任務從隊列被列出是按覅佛規(guī)則的,但是回并行執(zhí)行,執(zhí)行完成的順序是隨機的。適合并行處理數(shù)量龐大的任務,GCD可以自動生成四種此類并行隊列,只通過各自的優(yōu)先級不同去區(qū)別開來,當然你可以自己根據(jù)需要定義自己的并行隊列。因為此隊列對于你得應用程序來說是全局的,所以你并不需要關心它的引用計數(shù),即使給它retain或者release,都會被忽略。
dispatch_get_global_queue(<#dispatch_queue_priority_t priority#>, <#unsigned long flags#>)
DISPATCH_QUEUE_PRIORITY_HIGH 2
DISPATCH_QUEUE_PRIORITY_DEFAULT 0
DISPATCH_QUEUE_PRIORITY_LOW (-2)
DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN
Serial - private dispatch queues
- 通常用于訪問特定資源和數(shù)據(jù),多個serial queue之間同步并發(fā)執(zhí)行,串行fifo隊列,適合用于按指定順序執(zhí)行的任務,保持線程安全,串行同步安全地訪問資源,在應用程序里面,必須明確指定串行隊列,可以已根據(jù)需要創(chuàng)建足夠多的,但不要用serial queue 代替 concurrent queue 處理任務龐大的任務。
dispatch_queue_create(<#const char *label#>, <#dispatch_queue_attr_t attr#>)
使用
dispatch_once
- dispatch_once執(zhí)行一個區(qū)塊對象,在整個應用的生命周期只執(zhí)行一次,非常適合用于已單列模式創(chuàng)建全局的對象。
Executes a block object once and only once for the lifetime of an application.//官方解釋
void dispatch_once(
dispatch_once_t *predicate,
dispatch_block_t block);
// example
+(instancetype)shareDefaultManager
{
static TBReachabilityManager *_tbDefaultManager = nil;
static dispatch_once_t once_t;
dispatch_once(&once_t, ^(){
_tbDefaultManager = [[self alloc]init];
});
return _tbDefaultManager;
}
dispatch_async
- 提交一個block到一個異步執(zhí)行的隊列,執(zhí)行完成后馬上返回
Submits a block for asynchronous execution on a dispatch queue and returns immediately.
void dispatch_async(
dispatch_queue_t queue,
dispatch_block_t block);
* queue
block提交得目標隊列,在block執(zhí)行完成之前,系統(tǒng)會保留這個queue,值不能為Null
* block
隊列執(zhí)行的目標block,方法會自動執(zhí)行Block_copy和Block_release,值不能為Null
提交bolck到dispatch_queue最基本的方法,隊列決定block執(zhí)行的方式,串行或者并行,當然了,是異步的。
常用的方法
我們在處理一些耗時操作時,比如網(wǎng)絡讀取數(shù)據(jù)、預服務器交互、數(shù)據(jù)庫讀寫、io等,有時執(zhí)行時間過長會導致主界面有卡頓的甚至卡死的情況出現(xiàn),當然這種情況可以使用NSThread、NSOperation解決,但使用dispatch_async更簡單:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 耗時的操作,讀取數(shù)據(jù)、數(shù)據(jù)處理等操作
dispatch_async(dispatch_get_main_queue(), ^{
// 更新界面,dispatch_get_main_queue()是切換回主線程隊列的方法
});
});
dispatch_group_async
- 以組的方式關聯(lián)一組block,等block都執(zhí)行完成,就發(fā)起完成的通知,
group里面的block是并行執(zhí)行的
。
<br >
Submits a block to a dispatch queue and associates the block with the specified dispatch group.
void dispatch_group_async(
dispatch_group_t group,
dispatch_queue_t queue,
dispatch_block_t block);
使用例子
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, ^{
[NSThread sleepForTimeInterval:1];
NSLog(@"group1");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2];
NSLog(@"group2");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:3];
NSLog(@"group3");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"updateUi");
});
dispatch_release(group);//釋放group
這里面最后還調(diào)用了dispatch_group_notify,因為前面提交的block都被關聯(lián)到同一個group里面,當group里面的block都執(zhí)行完成后,就需要調(diào)用dispatch_group_notify做收尾。
dispatch_apply
- 多次執(zhí)行傳入的block
Submits a block to a dispatch queue for multiple invocations.
void dispatch_apply(
size_t iterations,
dispatch_queue_t queue,
void (^block)(
size_t));
dispatch_apply(10, global, ^(size_t index) {
// 執(zhí)行10次
});