Grand Central Dispatch(GCD)是異步執(zhí)行任務(wù)的技術(shù)之一揣炕,一般將應(yīng)用程序中記述的線程管理用的代碼在系統(tǒng)級(jí)實(shí)現(xiàn)。開發(fā)者值需要定義想執(zhí)行的任務(wù)并追加到適當(dāng)?shù)腄ispatch Queue中债朵,GCD就生成必要的線程并計(jì)劃執(zhí)行任務(wù)子眶。由于線程管理是作為系統(tǒng)的一部分來實(shí)現(xiàn)的,因此可以統(tǒng)一管理序芦,也可以執(zhí)行任務(wù)臭杰,這樣就比以前用線程更有效率。
GCD使用舉例
dispatch_async(queue,^{
/*
* 長(zhǎng)時(shí)間處理任務(wù)(如AR圖像識(shí)別谚中,數(shù)據(jù)庫訪問等)
*/
dispatch_async(dispatch_get_main_queue(),^{
/*
* 只在主線程執(zhí)行的任務(wù)渴杆,例如界面的更新
*/
});
});
GCD的API
Dispatch Queue
Dispatch Queue的種類 | 說明 |
---|---|
Serial Dispatch Queue | 串行線程 |
Concurrent Dispatch Queue | 并行線程 |
dispatch queue是線程執(zhí)行處理的等待隊(duì)列,應(yīng)用程序通過dispatch_async
等API將執(zhí)行的任務(wù)追加到Queue中藏杖。
一共存在兩種Dispatch Queue 将塑。
Dispatch Queue的種類 | 說明 |
---|---|
Serial Dispatch Queue | 串行線程 |
Concurrent Dispatch Queue | 并行線程 |
當(dāng)隊(duì)列為
serial
類型時(shí),只有一個(gè)線程蝌麸,并且任務(wù)按照串行執(zhí)行点寥。當(dāng)隊(duì)列為
concurrent
類型時(shí),不止一個(gè)線程来吩,任務(wù)是并發(fā)執(zhí)行敢辩。
獲取dispatch queue
使用dispathc_queue_create
創(chuàng)建
使用GCD的API生成dispatch queue。
dispatch_queue_t mySerialDispatchQueue = dispatch_queue_create("com.test.MySerialDispatchQueu",NULL);
第一個(gè)參數(shù)代表線程的名字弟疆,第二個(gè)參數(shù)NULL
代表使用serial dispatch queue
也就是串行的隊(duì)列戚长,如果要使用concurrent dispatch queue
需要傳入DISPATCH_QUEUE_CONCURRENT
。
Serial Dispatch Queue
生成的數(shù)量應(yīng)該僅限于必須要使用的串行線程數(shù)量怠苔,例如更行數(shù)據(jù)庫時(shí)一個(gè)表生成一個(gè)同廉。因?yàn)槊可梢粋€(gè)Serial Dispatch Queue
系統(tǒng)就會(huì)生成一條線程,造成內(nèi)存和時(shí)間的消耗柑司。
當(dāng)執(zhí)行不發(fā)生數(shù)據(jù)競(jìng)爭(zhēng)的問題的時(shí)迫肖,用Concurrent Dispatch Queue
。不管生成多少個(gè)Concurrent Dispatch Queue
攒驰,系統(tǒng)都能有效管理線程蟆湖,不會(huì)出現(xiàn)Serial Dispatch Queue
的問題。
注意:使用
dispathc_queue_create
創(chuàng)建的線程使用結(jié)束后要進(jìn)行釋放
使用dispatch_release
釋放:即Dispatch Queue 和 Objective-C的引用計(jì)數(shù)管理內(nèi)存一樣玻粪,需要使用dispatch_retain
和dispatch_release
進(jìn)行內(nèi)存管理
dispatch_queue_t queue = dispatch_create("com.test.MyConcurrentDispatchQueue",DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue,^{NSLog(@"block on queue")});
dispatch_release(queue);
Block
也會(huì)持有queue
所以不用擔(dān)心在第三行之后隅津,queue
對(duì)象銷毀,只有當(dāng)Block
也執(zhí)行完了劲室,才會(huì)進(jìn)行回收內(nèi)存伦仍。
使用系統(tǒng)提供的線程隊(duì)列
不用特意生成線程,系統(tǒng)也會(huì)提供幾個(gè)線程供使用
- Main Dispatch Queue:主線程很洋,只用一個(gè)
- Global Dispatch Queue:供所有程序使用的
concurrent dispatch queue
,另外這些線程有四個(gè)優(yōu)先級(jí)
名稱 | 種類 | 說明 |
---|---|---|
Main Dispatch Queue | Serial Dispatch Queue | 主線程執(zhí)行 |
Global Dispatch Queue(High Priority) | Concurrent Dispatch queue | 優(yōu)先級(jí)最高 |
Global Dispatch Queue(Default Priority) | Concurrent Dispatch queue | 默認(rèn) |
Global Dispatch Queue(Low Priority) | Concurrent Dispatch queue | 優(yōu)先級(jí)低 |
Global Dispatch Queue(Background Priority) | Concurrent Dispatch queue | 后臺(tái)執(zhí)行 |
// main dispatch queue 獲取
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
// global dispatch queue (High Priority) 獲取
dispatch_queue_t globalDispatchQueueHigh = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0);
使用系統(tǒng)提供的線程不需要自行進(jìn)行內(nèi)存管理呢铆。
更改使用dispatch_queue_create生成的queue的優(yōu)先級(jí)
使用dispatch_queue_create
生成的queue的優(yōu)先級(jí)和默認(rèn)的Global Dispatch Queue相同,可以使用dispatch_set_target_queue
來改變優(yōu)先級(jí)
Dispatch_after(做定時(shí)任務(wù))
比如3秒后處理一個(gè)任務(wù)
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW,3ull*NSEC_PER_SEC);
dispatch_after(time,queue,^{
// 任務(wù)
});
注意蹲缠,這里的3秒是3秒后加入任務(wù)棺克,不是精確的3秒悠垛,任務(wù)開始的最短時(shí)間在3秒后,最長(zhǎng)在3秒加一個(gè)時(shí)間片娜谊。
3ull
中的ull代表unsigned long long 無符號(hào)長(zhǎng)整型确买。
dispatch_group
- 創(chuàng)建group
dispatch_group_t dispatch_group_create(void);
- 給任務(wù)設(shè)置group
void dispatch_group_async(dispatch_group_t group,dispatch_queue_t queue,dispatch_block_t block);
- group里的任務(wù)全部執(zhí)行完后執(zhí)行最后一個(gè)任務(wù)
dispatch_group_notify(group,dispatch_get_main_queue(),^{NSlog(@"done");});
- 等待group完成
long dispatch_group_wait(dispatch_group_t group,dispatch_time_t timeout);
dispatch_barrier_async
在訪問數(shù)據(jù)庫或者文件的使用,如上所述纱皆,可以使用串行隊(duì)列來避免競(jìng)爭(zhēng)湾趾。
而讀取不會(huì)發(fā)生競(jìng)爭(zhēng)可以用并行線程。
也就是說派草,為了高效率地進(jìn)行訪問搀缠,讀取處理追加到Concurrent Dispatch Queue中,寫入處理在任一個(gè)讀取處理沒有執(zhí)行的狀態(tài)下近迁,追加到Serial Dispatch Queue中艺普。
這種情況可以使用dispatch_barrier_async
來解決讀取的問題。
dispatch_sync
dispatch_async是異步執(zhí)行的鉴竭。
dispatch_sync是同步執(zhí)行的歧譬。
dispatch_suspend/dispatch_resume
掛起和恢復(fù)queue
信號(hào)量
- 創(chuàng)建
dispatch_semaphore_t
dispatch_semaphore_create(long value);
- 觸發(fā)信號(hào)量
long dispatch_semaphore_signal(dispatch_samaphore_t dsema); //成功后 value++
- 等待信號(hào)量
long dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout); //成功后 value --