GCD -Grand Central Dispatch
GCD包含于libdispatch.dylib绸硕,系統(tǒng)默認(rèn)加載這個(gè)庫
GCD 是純C語言的,函數(shù)大多以dispatch開頭魂毁。
任務(wù)和隊(duì)列
任務(wù)
既是要執(zhí)行什么任務(wù)玻佩。
隊(duì)列
既是存放任務(wù)的。
定制任務(wù)
確定想做的事情
將任務(wù)添加到隊(duì)列中席楚,GCD會(huì)自動(dòng)將隊(duì)列中的任務(wù)取出咬崔,放到對應(yīng)的線程中執(zhí)行
提示:任務(wù)的取出遵循隊(duì)列的FIFO原則:先進(jìn)先出,后進(jìn)后出
執(zhí)行任務(wù)
GCD中有2個(gè)用來執(zhí)行任務(wù)的函數(shù):
同步方式:dispatch_sync(dispatch_quene_t queue,dispatch_block_t block)
異步方式:dispatch_async(dispatch_queue_t queue,dispatch_block_t block)
把block中的任務(wù)提交給queue隊(duì)列來執(zhí)行
同步(dispatch_sync)和異步(dispatch_async)的區(qū)別
同步:在當(dāng)前線程中執(zhí)行
異步:在另一條線程中執(zhí)行
隊(duì)列
隊(duì)列的類型
GCD的隊(duì)列可以分為2大類型:并發(fā)隊(duì)列(Concurrent Dispatch Queue)和串行隊(duì)列(Serial Dispatch Queue)
并發(fā)隊(duì)列(Concurrent Dispatch Queue)
可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行(自動(dòng)開啟多個(gè)線程同時(shí)執(zhí)行任務(wù))烦秩,并發(fā)功能只有在異步函數(shù)(dispatch_async(dispatch_queue_t queue_t,dispatch_block_t block))中才有效刁赦。
串行隊(duì)列(Serial Dispatch Queue)
讓任務(wù)一個(gè)接著一個(gè)執(zhí)行(一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù))
Tips:容易混淆的幾個(gè)概念-同步闻镶、異步、并發(fā)丸升、串行
同步和異步?jīng)Q定要不要開啟新的線程
同步:在當(dāng)前線程中執(zhí)行任務(wù)铆农,不具備開啟新線程的能力
異步:在新的線程中執(zhí)行任務(wù),具備開啟新線程的能力
并發(fā)和串行決定了任務(wù)的執(zhí)行方式
并發(fā):多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行
串行:一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù)
串行隊(duì)列
使用dispatch_queue_create函數(shù)創(chuàng)建串行隊(duì)列
函數(shù)原型:
dispatch_queue_t dispatch_queue_create(const char *label,dispatch_queue_attr_t attr)
label:隊(duì)列名稱-C語言的字符串墩剖、attr:隊(duì)列屬性-一般用NULL即可
示例:dispatch_queue_t queue = dispatch_queue_create("com.jiakaotuan.Gcd",NULL);
dispatch_release(queue);//非ARC模式下手動(dòng)釋放創(chuàng)建的隊(duì)列
并發(fā)隊(duì)列
GCD默認(rèn)已經(jīng)提供了全局的并發(fā)隊(duì)列猴凹,供整個(gè)應(yīng)用使用,不需要手動(dòng)創(chuàng)建
使用dispatch_get_global_queue函數(shù)獲得全局的并發(fā)隊(duì)列
函數(shù)原型:
dispatch_queue_t dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags)
priority:隊(duì)列優(yōu)先級(jí)岭皂,flags:保留的參數(shù)-傳0即可郊霎。
priority代表全局隊(duì)列的優(yōu)先級(jí),有以下幾個(gè)選項(xiàng)
全局并發(fā)隊(duì)列的優(yōu)先級(jí)
\\#define DISPATCH_QUEUE_PRIORITY_HIGH 2 // 高
\\#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 // 默認(rèn)(中)
\\#define DISPATCH_QUEUE_PRIORITY_LOW (-2) // 低
\\#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN // 后臺(tái)
各種隊(duì)列的執(zhí)行效果
全局并發(fā)隊(duì)列手動(dòng)創(chuàng)建串行隊(duì)列主隊(duì)列
同步(sync)沒有開啟新線程,串行執(zhí)行隊(duì)列沒有開啟新線程爷绘,串行執(zhí)行任務(wù)沒有開啟新線程书劝,串行執(zhí)行任務(wù)
異步(async)有開啟新線程,并發(fā)執(zhí)行任務(wù)有開啟新線程串行執(zhí)行任務(wù)沒有開啟新線程土至,串行執(zhí)行任務(wù)
GCD
1.dispatch_async
1.為了避免界面在處理耗時(shí)的操作時(shí)卡死购对,比如讀取網(wǎng)絡(luò)數(shù)據(jù),IO陶因,數(shù)據(jù)庫讀寫等骡苞,我們會(huì)在另外一個(gè)線程中處理這些耗時(shí)的操作,處理完成之后在主線程更新UI界面楷扬。(記住UI的更新只能在主線程哦)
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY,0)),^{
NSURL *url = [NSURL URLWithString:@"http://c.hiphotos.baidu.com/image/h%3D200/sign=a7b8619c4e540923b569647ea259d1dc/50da81cb39dbb6fd786f7a990e24ab18972b375c.jpg"];
NSData *data = [[NSData alloc]initWithContentsOfURL:url];
UIImage *image = [[UIImage alloc]initWithData:data];
if(data != nil && image != nil){
dispatch_async(dispatch_get_main_queue(),^{
self.imageView.image = image;
}
}
}
2.獲取global_queue
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
3.獲取main_queue
dispatch_queue_t mainQueue = dispatch_get_main_queue();
2.dispatch_group_async
dispatch_group_async可以監(jiān)聽一組任務(wù)是否完成解幽,完成后得到通知執(zhí)行其他的操作。比如你進(jìn)行了2個(gè)下載任務(wù)烘苹,當(dāng)這2個(gè)下載任務(wù)都完成后你通知界面刷新UI躲株。
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(@"one");
}
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,queue,^{
[NSThread sleepForTimeInterval:2];
NSLog(@"two");
}
dispatch_group_notify(group,dispatch_get_main_queue(),^{
NSLog(@"updateUI");
}
dispatch_release(group);
diapatch_group_async是異步的方法,運(yùn)行結(jié)果如下
one
two
updateUI
可以看到在打印完one和two之后再打印的updateUI
3.dispatch_barrier_async
dispatch_barrier_async是在前面的任務(wù)執(zhí)行完畢之后才開始執(zhí)行的,同理要等它執(zhí)行完畢之后螟加,它后面的任務(wù)才會(huì)開始執(zhí)行徘溢。
dispatch_queue_t queue = dispatch_queue_create("gcdDemo",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue,^{
[NSThread sleepForTimeInterval:2];
NSLog(@"dispatch_async_after_2s");
})
dispatch_async(queue,^{
[NSThread sleepForTimeInterval:4];
NSLog(@"dispatch_async_after_4s");
})
dispatch_barrier_async(queue,^{
NSLog(@"dispatch_barrier_async");
[NSThread sleepForTimeInterval:4];
})
dispatch_async(queue,^{
[NSThread sleepForTimeInterval:1];
NSLog(@"dispatch_async_after_1s");
})
注意看打印的時(shí)間:
打印時(shí)間打印內(nèi)容說明
16:20:33.900dispatch_async_after_2s在33s的時(shí)候打印的
16:20:35.900dispatch_async_after_4s在35s的時(shí)候打印的,和上一個(gè)打印相差2s=(4s-2s)
16:20:35.900dispatch_barrier_async在35s的時(shí)候打印的捆探,是在上一個(gè)結(jié)束之后打印的
16:20:40.900dispatch_async_after_1s在40s的時(shí)候打印的然爆,在上一個(gè)打印結(jié)束之后,睡了4s后又睡了1s才打印的黍图,所以和上一個(gè)打印相差5s=(4s+1s)
4.dispatch_apply
執(zhí)行某個(gè)代碼片段N次
dispatch_apply(N,globalQ,^(size_t index){
//執(zhí)行N次
});
文/志城(簡書作者)
原文鏈接:http://www.reibang.com/p/7ae752507800
著作權(quán)歸作者所有曾雕,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標(biāo)注“簡書作者”助被。