文章資料來源《Objective-C高級(jí)編程》之GCD
GCD是一種異步執(zhí)行任務(wù)的技術(shù),對(duì)于編程層面上異步執(zhí)行就意味著創(chuàng)建一個(gè)線程(操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位谱醇,是進(jìn)程中一個(gè)單一順序的控制流--from wiki)去執(zhí)行Task醇疼;GCD提供了兩種隊(duì)列和相關(guān)API使得開發(fā)者只需要關(guān)心該選擇哪種隊(duì)列去執(zhí)行任務(wù)即可;
GCD的隊(duì)列
- serial queue 能夠保證各個(gè)task在同一個(gè)線程中被執(zhí)行并且執(zhí)行順序會(huì)嚴(yán)格的按照入隊(duì)的順序進(jìn)行听想;
- concurrent queue 各個(gè)task的執(zhí)行互不影響掏秩,執(zhí)行順序上不確定,執(zhí)行線程也不一定會(huì)相同兴喂;
dispatch_queue_create 創(chuàng)建隊(duì)列
serial queue
/*
1>serial Queue:系統(tǒng)默認(rèn)創(chuàng)建一個(gè)線程蔼囊,隊(duì)列中的任務(wù)是順序執(zhí)行
2>創(chuàng)建多個(gè)serial queue 的執(zhí)行是并發(fā)的沒有順序
3>解決數(shù)據(jù)競爭問題:可以將任務(wù)放在serial queue中 保證任務(wù)按照順序執(zhí)行就能解決數(shù)據(jù)競爭
*/
dispatch_queue_t mySerialQueue = dispatch_queue_create("com.hua.example.serialQueue", DISPATCH_QUEUE_SERIAL);
concurrent queue
/*
1 concurrent queue 添加到隊(duì)列中的任務(wù)會(huì)并發(fā)執(zhí)行,沒有順序性
*/
dispatch_queue_t myConcurrentQueue=dispatch_queue_create("com.hua.example.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
非ARC下生成的隊(duì)列還必須使用dispatch_release(Queue);
來釋放指定的隊(duì)列
Main Dispatch Queue and Global Dispatch Queue
Main Dispatch Queue
/*
dispatch_get_main_queue
(1)main queue 是一中serial queue衣迷,task是放在主線程的Runloop中執(zhí)行的畏鼓;
(2)一些UI的更新操作需要放在主線程中,使用main queue是比較簡單的
*/
dispatch_queue_t main_queue = dispatch_get_main_queue();
global Dispatch Queue
/*
dispatch_get_global_queue
(1)global queue 是一種concurrent queue壶谒,可以通過設(shè)置queue的priority指定執(zhí)行的優(yōu)先級(jí)云矫;
*/
dispatch_queue_t global_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_set_target_queue
/*
dispatch_set_target_queue的第一個(gè)參數(shù)是指定要變更優(yōu)先級(jí)的隊(duì)列;指定與要使用優(yōu)先級(jí)相同優(yōu)先級(jí)的隊(duì)列為第二個(gè)參數(shù)
*/
dispatch_queue_t serialqueue1 = dispatch_queue_create("serialqueue1", NULL);
dispatch_queue_t serialqueue2 = dispatch_queue_create("serialqueue2", NULL);
dispatch_set_target_queue(serialqueue2, serialqueue1);
/*
dispatch_after
/*
延遲若干時(shí)間處理某一個(gè)Task汗菜,只是追加task到某一個(gè)隊(duì)列让禀,并不一定立即執(zhí)行task
*/
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);
dispatch_after(time, dispatch_get_main_queue(), ^{
NSLog(@"wait at least three seconds!!");
});
dispatch Group
dispatch group 的出現(xiàn)可以解決多個(gè)并發(fā)task執(zhí)行后能收到通知再執(zhí)行其他任務(wù)操作的需求;
/*
1; 如果使用 serial queue 所有的task執(zhí)行完畢后在執(zhí)行done task
2:如果使用 concurrent queue 所有的task執(zhí)行后沒辦法 執(zhí)行行done task 就需要 dispatch_group
*/
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, ^{
NSLog(@"blok1");
});
dispatch_group_async(group, queue, ^{
NSLog(@"blok2");
});
dispatch_group_async(group, queue, ^{
NSLog(@"blok3");
});
dispatch_group_async(group, queue, ^{
[NSThread sleepForTimeInterval:2.0];
NSLog(@"blok4");
});
// 監(jiān)聽group 中的task 是否已經(jīng)全部執(zhí)行完成
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"done!!");
});
// dispatch_group_wait會(huì)hold住當(dāng)前線程直到所有task執(zhí)行完畢
// dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
NSLog(@"all finish!!!!");
多個(gè)網(wǎng)絡(luò)請(qǐng)求執(zhí)行操作完成在執(zhí)行下一步操作的需求如何實(shí)現(xiàn)陨界?
// 多個(gè)網(wǎng)絡(luò)請(qǐng)求完成后再做新的任務(wù)
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//網(wǎng)絡(luò)請(qǐng)求操作1
dispatch_group_leave(group);
});
dispatch_group_enter(group);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//網(wǎng)絡(luò)請(qǐng)求操作2
dispatch_group_leave(group);
});
dispatch_barrier_async
多線程操作產(chǎn)生的一個(gè)問題就是數(shù)據(jù)資源的競爭巡揍,讀寫操作如何能保證線程安全性;dispatch_barrier_async提供了解決方案
/*
使用concurrent dispatch queue 和 dispatch barrier async 函數(shù)可實(shí)現(xiàn)高效率的數(shù)據(jù)庫訪問和文件讀取
*/
dispatch_queue_t queue = dispatch_queue_create("test.concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(queue, ^{
NSLog(@"task1forReading!");
});
dispatch_async(queue, ^{
NSLog(@"task2forReading!");
});
dispatch_async(queue, ^{
NSLog(@"task3forReading!");
});
dispatch_barrier_async(queue, ^{
// 此taskforWriting 會(huì)等到加入concurrentQueue中的task執(zhí)行完畢后菌瘪,執(zhí)行taskforWriting腮敌,等到該taskforWriting執(zhí)行完畢后在執(zhí)行 concurrentQueue中的task
NSLog(@"taskforWriting!");
});
dispatch_async(queue, ^{
NSLog(@"task4forReading!");
});
dispatch_async(queue, ^{
NSLog(@"task5forReading!");
});
dispatch_sync
/*
dispatch_sync 函數(shù)意味著等待;它要等待task執(zhí)行完畢后再做返回
*/
//使用dispatch_sync 容易造成死鎖
//在主線程中執(zhí)行以下源代碼會(huì)造成死鎖
/*
main_queue 是一個(gè)serialQueue 俏扩,使用dispatch_sync將task加入到mainqueue中task會(huì)等待mainqueue中的任務(wù)執(zhí)行完成糜工,而mainqueue又要等待task完成,由此造成了死鎖录淡;
*/
dispatch_queue_t main_queue = dispatch_get_main_queue();
dispatch_sync(main_queue, ^{
NSLog(@"hello dispatch_sync!");
});
//>2在主線程中執(zhí)行以下源代碼也會(huì)造成死鎖
dispatch_async(main_queue, ^{
dispatch_sync(main_queue, ^{
NSLog(@"hello!!");
});
});
dispatch_apply
NSMutableArray* tempArr = [@[@"key1",@"key2",@"key3",@"key4",@"key5"] mutableCopy];
// 1 按照指定的次數(shù)將指定的Block追加到指定的Dispatch_Queue中捌木,并等待全部處理執(zhí)行結(jié)束
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply([tempArr count], queue, ^(size_t index) {
// 要做數(shù)據(jù)更新操作
NSLog(@"%d",index);
});
NSLog(@"task done");
/*
1 對(duì)數(shù)組進(jìn)行循環(huán)遍歷的方法
1》 for循環(huán)
2》 block
3》 dispatch_apply
2 dispatch_apply 要等待結(jié)束,最好和 dispatch_async函數(shù)混合使用
*/
掛起隊(duì)列和執(zhí)行隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//掛起隊(duì)列
dispatch_suspend(queue);
//恢復(fù)指定隊(duì)列
dispatch_resume(queue);
dispatch_Semaphore
// 1 向數(shù)組中增加對(duì)象由于內(nèi)存錯(cuò)誤導(dǎo)致異常的概率會(huì)很高
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
NSMutableArray* mutable_arr =[NSMutableArray array];
for(int i = 0;i<100000;++i)
{
dispatch_async(queue, ^{
[mutable_arr addObject:[NSNumber numberWithInt:i]];
});
}
// 2 使用dispatch_semaphore進(jìn)行更細(xì)粒度的線程管理
dispatch_queue_t global_queue = dispatch_queue_create(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
/*
生成Dispatch Semahpore
dispatch_Semahpore 的計(jì)數(shù)初始值設(shè)定為“1”
這樣能保證訪問NSMutableArray類對(duì)象的線程嫉戚,同時(shí)只有1個(gè)
*/
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
NSMutableArray* array =[NSMutableArray array];
for(int i = 0;i<10000;i++)
{
dispatch_async(global_queue, ^{
/*
等待Dispatch Semaphore
直到Dispatch Semphore的計(jì)數(shù)值達(dá)到大于等于1刨裆;
*/
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
/*
由于dispatch Semaphore 的計(jì)數(shù)值達(dá)到大于等于1
所以將Dispatch semaphore 的計(jì)數(shù)值減去1
dispatch_semaphore_wait 函數(shù)執(zhí)行返回
執(zhí)行到此 dispatch Semaphore的計(jì)數(shù)值恒為“0”
*/
[array addObject:[NSNumber numberWithInt:i]];
/*
排他控制處理結(jié)束,所以通過dispatch_semaphore_signal函數(shù) 將
Dispatch Semaphore的計(jì)數(shù)值加1
如果有通過dispatch_semaphore_wait 函數(shù) 等待dispatch Semaphore 的計(jì)數(shù)值增加的線程 就由最先等待的線程執(zhí)行
*/
dispatch_semaphore_signal(semaphore);
});
}
dispatch_once
保證應(yīng)用程序中只執(zhí)行一次指定處理的API
+(instancetype)shareInstance
{
static ViewController* _vc;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_vc =[[self alloc] init];
});
return _vc;
}