GCD的基本思想
-
GCD的基本思想是將操作放在隊(duì)列中去執(zhí)行
(1)操作使用block定義睁搭。
(2)隊(duì)列負(fù)責(zé)調(diào)度任務(wù)執(zhí)行所在的線程以及具體的執(zhí)行時(shí)間。
(3)隊(duì)列的特點(diǎn)是先進(jìn)先出想许,新添加到隊(duì)列的操作排在最后慰技。
-
隊(duì)列 dispatch_queue_t
(1) DISPATCH_QUEUE_SERIAL:串行隊(duì)列,隊(duì)列中的任務(wù)只會(huì)順序執(zhí)行娘摔。
(2) DISPATCH_QUEUE_CONCURRENT:并行隊(duì)列,隊(duì)列中的任務(wù)通常會(huì)并發(fā)執(zhí)行唤反。
-
操作
dispatch_async 異步操作凳寺,會(huì)并發(fā)執(zhí)行,不會(huì)順序執(zhí)行彤侍。
dispatch_sync 同步操作肠缨,會(huì)依次順序執(zhí)行,能決定任務(wù)執(zhí)行的順序盏阶。
一晒奕、DISPATCH_QUEUE_SERIAL: 串行隊(duì)列:
- (void) GCD
{
//DISPATCH_QUEUE_SERIAL串行隊(duì)列,會(huì)死鎖,但是會(huì)執(zhí)行嵌套同步操作之前的代碼
dispatch_queue_t queue = dispatch_queue_create("queue1", DISPATCH_QUEUE_SERIAL);
dispatch_async(queue, ^{
NSLog(@"讀書===%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"吃飯====%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"上廁所====%@", [NSThread currentThread]);
});
}
2016-04-13 16:24:22.100 test[25089:1136445] 讀書===<NSThread: 0x7fb050700ee0>{number = 2, name = (null)}
2016-04-13 16:24:22.101 test[25089:1136445] 吃飯====<NSThread: 0x7fb050700ee0>{number = 2, name = (null)}
2016-04-13 16:24:22.102 test[25089:1136445] 上廁所====<NSThread: 0x7fb050700ee0>{number = 2, name = (null)}
可以看出來(lái)當(dāng)操作方式是dispatch_async時(shí)脑慧,只有兩個(gè)隊(duì)列魄眉,一個(gè)主線程,一個(gè)子線程闷袒,在子線程中執(zhí)行三個(gè)方法坑律,所以異步操作是可以創(chuàng)建新線程的,而且操作會(huì)順序執(zhí)行的囊骤,這個(gè)非常有用晃择,既不會(huì)影響主線程,又可以開啟新線程按順序執(zhí)行任務(wù)∫参铮現(xiàn)在把操作方式改為dispatch_sync看一下打印結(jié)果:
2016-04-13 17:33:42.131 test[25342:1168870] 讀書===<NSThread: 0x7f8118d03bb0>{number = 1, name = main}
2016-04-13 17:33:42.131 test[25342:1168870] 吃飯====<NSThread: 0x7f8118d03bb0>{number = 1, name = main}
2016-04-13 17:33:42.132 test[25342:1168870] 上廁所====<NSThread: 0x7f8118d03bb0>{number = 1, name = main}
可以看出來(lái)只有一個(gè)線程宫屠,也就是主線程,所以證明了dispatch_sync是沒有開啟新線程的能力的滑蚯。
二浪蹂、DISPATCH_QUEUE_CONCURRENT:并行隊(duì)列
我們?cè)侔殃?duì)列的屬性改成DISPATCH_QUEUE_CONCURRENT試試,看下打印結(jié)果:
2016-04-13 17:44:38.296 test[25402:1175291] 上廁所====<NSThread: 0x7fdfe8f288a0>{number = 4, name = (null)}
2016-04-13 17:44:38.296 test[25402:1175301] 讀書===<NSThread: 0x7fdfe8f2bf10>{number = 2, name = (null)}
2016-04-13 17:44:38.296 test[25402:1175307] 吃飯====<NSThread: 0x7fdfe8e21cd0>{number = 3, name = (null)}
首先告材,可以看出乌逐,當(dāng)隊(duì)列的屬性是DISPATCH_QUEUE_CONCURRENT時(shí),任務(wù)會(huì)無(wú)序執(zhí)行的创葡,而且并行隊(duì)列DISPATCH_QUEUE_CONCURRENT是可以開啟新線程的。
得出結(jié)果當(dāng)隊(duì)列的屬性是DISPATCH_QUEUE_CONCURRENT并行隊(duì)列绢慢,操作是異步操作dispatch_async時(shí)灿渴,會(huì)創(chuàng)建多個(gè)線程,操作無(wú)序執(zhí)行胰舆。但是如果隊(duì)列錢有其他任務(wù)骚露,會(huì)等待其他任務(wù)執(zhí)行完成后再執(zhí)行其他的任務(wù)。適合的操作為:既不影響主線程缚窿,又不需要順序執(zhí)行的操作棘幸。
然后,我們?cè)侔巡僮鞲臑閐ispatch_sync,看下打印結(jié)果:
2016-04-13 18:08:17.944 test[25521:1187204] 讀書===<NSThread: 0x7fe74ac05610>{number = 1, name = main}
2016-04-13 18:08:17.944 test[25521:1187204] 吃飯====<NSThread: 0x7fe74ac05610>{number = 1, name = main}
2016-04-13 18:08:17.945 test[25521:1187204] 上廁所====<NSThread: 0x7fe74ac05610>{number = 1, name = main}
可以看出倦零,無(wú)論隊(duì)列的方式是串行隊(duì)列還是并行隊(duì)列误续,dispatch_sync同步操作方式都是不會(huì)創(chuàng)建新線程的,任務(wù)只會(huì)在主線程中執(zhí)行扫茅。
三蹋嵌、dispatch_get_global_queue():全局隊(duì)列
看下面一段代碼:
- (void) globalQueue
{
//全局隊(duì)列,都在主線程中執(zhí)行葫隙,不會(huì)死鎖栽烂,
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSLog(@"讀書===%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"吃飯====%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"上廁所====%@", [NSThread currentThread]);
});
}
結(jié)果:
2016-04-13 18:16:18.646 test[25609:1191848] 吃飯====<NSThread: 0x7f91c940db00>{number = 3, name = (null)}
2016-04-13 18:16:18.650 test[25609:1191841] 讀書===<NSThread: 0x7f91c9659890>{number = 2, name = (null)}
2016-04-13 18:16:18.646 test[25609:1191855] 上廁所====<NSThread: 0x7f91c940fa50>{number = 4, name = (null)}
全局隊(duì)列是系統(tǒng)的,無(wú)序創(chuàng)建,直接用即可腺办,可以看出焰手,全局隊(duì)列與并行隊(duì)列類型,但是調(diào)試時(shí)怀喉,無(wú)法確認(rèn)操作所在隊(duì)列书妻。
當(dāng)操作方式為dispatch_sync時(shí),不再做解析磺送,雷同上面驻子。
四、dispatch_get_main_queue():主隊(duì)列
看下面一段代碼:
- (void) mainQueue
{
//直接死鎖
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
NSLog(@"讀書===%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"吃飯====%@", [NSThread currentThread]);
});
dispatch_async(queue, ^{
NSLog(@"上廁所====%@", [NSThread currentThread]);
});
}
結(jié)果:
2016-04-13 18:35:50.259 test[25749:1204150] 讀書===<NSThread: 0x7fc9f8e05c30>{number = 1, name = main}
2016-04-13 18:35:50.264 test[25749:1204150] 吃飯====<NSThread: 0x7fc9f8e05c30>{number = 1, name = main}
2016-04-13 18:35:50.264 test[25749:1204150] 上廁所====<NSThread: 0x7fc9f8e05c30>{number = 1, name = main}
每一個(gè)應(yīng)用程序中只有一個(gè)主隊(duì)列估灿,直接使用即可無(wú)需創(chuàng)建崇呵,常常在主隊(duì)列中更新UI。主隊(duì)列中的操作都應(yīng)該自主隊(duì)列中執(zhí)行馅袁,不存在異步的概念域慷。除非主線程被用戶殺掉,否則永遠(yuǎn)不會(huì)結(jié)束汗销。
五犹褒、dispatch_sync的應(yīng)用場(chǎng)景(登陸操作)。dispatch_sync會(huì)阻塞并行隊(duì)列的執(zhí)行弛针,要求某一操作執(zhí)行完成之后才會(huì)執(zhí)行下一個(gè)操作叠骑。
- (void) newThread
{
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);
__block BOOL logon = NO;
dispatch_sync(q, ^{ //同步
NSLog(@"模擬耗時(shí)操作 %@", [NSThread currentThread]);
[NSThread sleepForTimeInterval:2.0f];//停留兩秒鐘,模仿耗時(shí)操作
NSLog(@"模擬耗時(shí)完成 %@", [NSThread currentThread]);
logon = YES;
});
dispatch_async(q, ^{
NSLog(@"登錄完成的處理 %@", [NSThread currentThread]);
});
}
結(jié)果:
2016-04-14 10:47:24.117 test[26976:1276763] 模擬耗時(shí)操作 <NSThread: 0x7fe3a8d054e0>{number = 1, name = main}
2016-04-14 10:47:26.119 test[26976:1276763] 模擬耗時(shí)完成 <NSThread: 0x7fe3a8d054e0>{number = 1, name = main}
2016-04-14 10:47:26.119 test[26976:1276894] 登錄完成的處理 <NSThread: 0x7fe3a8c10f80>{number = 2, name = (null)}
六削茁、dispatch_barrier_async,在并行隊(duì)列中等待前面的操作執(zhí)行完成后宙枷,才恢復(fù)后面的執(zhí)行狀態(tài)。
- (void) dispatchBarrierAsync
{
dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^(){
NSLog(@"%@====dispatch-1", [NSThread currentThread]);
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"%@=====dispatch-2", [NSThread currentThread]);
});
dispatch_barrier_async(concurrentQueue, ^(){
NSLog(@"%@======dispatch-barrier", [NSThread currentThread]);
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"%@======dispatch-3", [NSThread currentThread]);
});
dispatch_async(concurrentQueue, ^(){
NSLog(@"%@======dispatch-4", [NSThread currentThread]);
});
}
結(jié)果:
2016-04-14 11:00:34.769 test[27143:1285750] <NSThread: 0x7ff80a70adb0>{number = 3, name = (null)}=====dispatch-2
2016-04-14 11:00:34.769 test[27143:1285758] <NSThread: 0x7ff80a40f460>{number = 2, name = (null)}====dispatch-1
2016-04-14 11:00:34.772 test[27143:1285758] <NSThread: 0x7ff80a40f460>{number = 2, name = (null)}======dispatch-barrier
2016-04-14 11:00:34.772 test[27143:1285758] <NSThread: 0x7ff80a40f460>{number = 2, name = (null)}======dispatch-3
2016-04-14 11:00:34.772 test[27143:1285750] <NSThread: 0x7ff80a70adb0>{number = 3, name = (null)}======dispatch-4
七茧跋、dispatch_group_t慰丛,當(dāng)有多個(gè)任務(wù)時(shí),可以把多個(gè)任務(wù)放到group里面瘾杭,group執(zhí)行完畢后再執(zhí)行其他任務(wù)诅病。
- (void) group
{
dispatch_queue_t queue = dispatch_queue_create("test", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, queue, ^{
NSLog(@"task1 begin=====%@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"task2 begin=====%@", [NSThread currentThread]);
});
dispatch_group_notify(group, queue, ^{
NSLog(@"======================%@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"task3 begin=====%@", [NSThread currentThread]);
});
dispatch_group_async(group, queue, ^{
NSLog(@"task4 begin=====%@", [NSThread currentThread]);
});
}
結(jié)果:
2016-04-14 11:35:54.676 test[27339:1300173] task1 begin=====<NSThread: 0x7fe3da606170>{number = 2, name = (null)}
2016-04-14 11:35:54.729 test[27339:1300202] task4 begin=====<NSThread: 0x7fe3da621660>{number = 5, name = (null)}
2016-04-14 11:35:54.729 test[27339:1300167] task2 begin=====<NSThread: 0x7fe3da6213a0>{number = 3, name = (null)}
2016-04-14 11:35:54.729 test[27339:1300178] task3 begin=====<NSThread: 0x7fe3da51f7b0>{number = 4, name = (null)}
2016-04-14 11:35:54.770 test[27339:1300178] ======================<NSThread: 0x7fe3da51f7b0>{number = 4, name = (null)}
可以看出,當(dāng)所有任務(wù)都執(zhí)行完畢后才執(zhí)行dispatch_group_notify中的任務(wù)粥烁。
看完這篇文章贤笆,相信大家對(duì)GCD有了詳細(xì)的了解,有問題歡迎大家一起探討页徐,下班回家吃飯去苏潜,哈哈。