多線程核心概念: 一個任務(wù) / 兩種隊列 / 兩種函數(shù).
1. 一個任務(wù): 執(zhí)行什么操作;
2. 執(zhí)行任務(wù)的兩種隊列:
(1)并發(fā)隊列(Concurrent Dispatch Queue): 可以讓多個任務(wù)并發(fā)(同時)執(zhí)行(自動開啟多個線程同時執(zhí)行任務(wù)),
前提是在dispatch_async異步函數(shù)下執(zhí)行;
(2)串行隊列(Serial Dispatch Queue):一個任務(wù)執(zhí)行完畢后,再執(zhí)行下一個任務(wù).
2.1 并發(fā)隊列和串行隊列的區(qū)別: 任務(wù)的執(zhí)行方式不同
---------------------------------------------------
3. 執(zhí)行任務(wù)的兩種函數(shù):
(1)同步函數(shù)dispatch_sync < synchronous>: 不具備開啟新線程的能力;
(2)異步函數(shù)dispatch_async <asynchronous>: 具備開啟新線程的能力
3.1 同步和異步區(qū)別:能不能開啟新的線程
多線程創(chuàng)建隊列的兩種方式
1. 通過dispatch_queue_create函數(shù)創(chuàng)建一個隊列;
2. 直接獲取現(xiàn)成的主線程dispatch隊列或者全局的dispatch隊列。
GCD實現(xiàn)的Timer如圖所示:
核心代碼:
//開始
- (IBAction)startTimer:(id)sender {
__block int startTimer = 0;
__weak typeof(self) weakself = self;
//開啟專門的線程處理timer
self.timerQueue = dispatch_queue_create("TimerQueue", 0);
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _timerQueue);
/*----打出dispatch_s直接就出現(xiàn)下邊的代碼塊了---------*/
/**
* 第一個參數(shù): dispatch_source_t, Dispatch Source
* 第二個參數(shù): 開始時刻;
* 第三個參數(shù): 間隔<例子中是一秒>;
* 第四個參數(shù): 精度<最高精度將之設(shè)置為0>
*/
dispatch_source_set_timer(self.timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//函數(shù)回調(diào)
dispatch_source_set_event_handler(self.timer, ^{
//回主線刷新UI
dispatch_async(dispatch_get_main_queue(), ^{
weakself.label.text = [NSString stringWithFormat:@"%d", startTimer++];
});
});
//默認(rèn)的dispatch_source_t是暫停, 開始監(jiān)聽
dispatch_resume(self.timer);
/*----打出dispatch_s直接就出現(xiàn)上邊的代碼塊了---------*/
}
dispatch_queue_create創(chuàng)建兩種隊列
//創(chuàng)建一個串行dispatch隊列, 第二個參數(shù)將其設(shè)置成NULL褥傍。
dispatch_queue_t mySerialDispatchQueue =
dispatch_queue_create("com.example.gcd", NULL);
//創(chuàng)建一個串行dispatch隊列, 第二個參數(shù)就設(shè)置成DISPATCH_QUEUE_CONCURRENT
dispatch_queue_t myConcurrentDispatchQueue =
dispatch_queue_create( "com.example.gcd.MyConcurrentDispatchQueue", DISPATCH_QUEUE_CONCURRENT);
具體操作
1.直接獲取線程的隊列
1. 主線程dispatch隊列: 所有任務(wù)都在主線程上執(zhí)行, 它是一個串行隊列。
dispatch_queue_t mainDispatchQueue = dispatch_get_main_queue();
--------------------------------------------------
2. 全局的dispatch隊列: 它是并行隊列浅悉,可以在應(yīng)用程序的任何地方使用它們崖咨。
一般可以直接使用該隊列. 有四種優(yōu)先級:high, default, low 和 background队萤。
dispatch_queue_t globalDispatchQueueDefault =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
2. dispatch_set_target_queue 設(shè)置優(yōu)先級
dispatch_set_target_queue函數(shù)用于設(shè)置一個”目標(biāo)”隊列米母。創(chuàng)建隊列后勾扭,你可以用這個函數(shù)來修改隊列的優(yōu)先級。
3. dispatch_group_async 分組
等dispatch隊列中的所有任務(wù)完成了才執(zhí)行另外一個任務(wù)铁瞒。
dispatch_group_async就可以上場了.
4. dispatch_barrier_async 柵欄方式
dispatch_barrier_async函數(shù)用于等待隊列中其他任務(wù)完成妙色。
1. 當(dāng)你訪問數(shù)據(jù)庫或者一個文件的時候,你可以用串行隊列來避免數(shù)據(jù)沖突慧耍。
2. 多個讀取操作是可以同時進行的身辨,這樣可以更高效的訪問數(shù)據(jù),但更新數(shù)據(jù)時必須等其他操作結(jié)束, 如果使用前兩種方式會很麻煩.
3. dispatch_barrier_async 創(chuàng)建了一個并發(fā)隊列芍碧,然后向隊列中添加了一些讀取操作煌珊。會等本次操作以前的完全執(zhí)行才執(zhí)行.
5. dispatch_apply
dispatch_apply函數(shù)會像dispatch_sync函數(shù)一樣等待所有任務(wù)完成,
//串行隊列是有序的
dispatch_apply(5, syncQueue, ^(size_t index) {
NSLog(@"++++++ %zu", index);
});
順序: 01234
//并發(fā)隊列是無序
dispatch_apply(5, asyncQueue, ^(size_t index) {
NSLog(@"----%zu", index);
});
順序不固定
6. dispatch_semaphore_t 信號量
并發(fā)讀取或更新數(shù)據(jù)時
很容易造成數(shù)據(jù)沖突或者程序崩潰泌豆。
當(dāng)你需要對一小部分間隔時間較短
的任務(wù)做并發(fā)控制
的時候定庵,Semaphore(信號量)會比串行隊列或者dispatch_barrier_async更好用。
Dispatch semaphore是一個帶有一個計數(shù)器的信號量踪危。信號量有點像一個交通信號標(biāo)志蔬浙,標(biāo)志起來的時候你
可以走,標(biāo)準(zhǔn)落下的時候你要停下來贞远。Dispatch semaphore用計數(shù)器來模擬這種標(biāo)志畴博。計數(shù)器為0,隊列暫停
執(zhí)行新任務(wù)并等待信號蓝仲;當(dāng)計數(shù)器超過0后俱病,隊列繼續(xù)執(zhí)行新任務(wù),并減少計數(shù)器袱结。
//用dispatch_semaphore_create函數(shù)庶艾。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
//dispatch_semaphore_wait函數(shù)用于等待一個信號量。
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC);
long result = dispatch_semaphore_wait(semaphore, time);
if (result == 0){
/*
* 信號量計數(shù)器大于等于1擎勘。
* 或者在指定的等待時間超時前咱揍,信號量計數(shù)器變成了大于等于1的數(shù)字。
* 計數(shù)器會自動減一
*
* 在這里棚饵,可以安全地運行你的任務(wù)了煤裙。
*/
}else{
/*
* 因為信號量計數(shù)器是0,就只能等待超時了噪漾。
*
* 這里處理等待超時的情況硼砰。
*/
}
GCD支持方法示例代碼
GCD實現(xiàn)的Timer代碼
更多精彩內(nèi)容請關(guān)注“IT實戰(zhàn)聯(lián)盟”哦~~~