iOS之淺談GCD

GCD的基本思想


  • GCD的基本思想是將操作放在隊列中去執(zhí)行
    (1)操作使用block定義。
    (2)隊列負責(zé)調(diào)度任務(wù)執(zhí)行所在的線程以及具體的執(zhí)行時間。
    (3)隊列的特點是先進先出,新添加到隊列的操作排在最后。
  • 隊列 dispatch_queue_t
    (1) DISPATCH_QUEUE_SERIAL:串行隊列,隊列中的任務(wù)只會順序執(zhí)行。
    (2) DISPATCH_QUEUE_CONCURRENT:并行隊列,隊列中的任務(wù)通常會并發(fā)執(zhí)行。
  • 操作
    dispatch_async 異步操作,會并發(fā)執(zhí)行,不會順序執(zhí)行。
    dispatch_sync 同步操作,會依次順序執(zhí)行,能決定任務(wù)執(zhí)行的順序。

一、DISPATCH_QUEUE_SERIAL: 串行隊列:
- (void) GCD
{

//DISPATCH_QUEUE_SERIAL串行隊列,會死鎖,但是會執(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)} 

可以看出來當(dāng)操作方式是dispatch_async時,只有兩個隊列,一個主線程,一個子線程,在子線程中執(zhí)行三個方法,所以異步操作是可以創(chuàng)建新線程的,而且操作會順序執(zhí)行的,這個非常有用,既不會影響主線程,又可以開啟新線程按順序執(zhí)行任務(wù)?,F(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}

可以看出來只有一個線程,也就是主線程,所以證明了dispatch_sync是沒有開啟新線程的能力的。

二、DISPATCH_QUEUE_CONCURRENT:并行隊列

我們再把隊列的屬性改成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)隊列的屬性是DISPATCH_QUEUE_CONCURRENT時,任務(wù)會無序執(zhí)行的,而且并行隊列DISPATCH_QUEUE_CONCURRENT是可以開啟新線程的。

得出結(jié)果當(dāng)隊列的屬性是DISPATCH_QUEUE_CONCURRENT并行隊列,操作是異步操作dispatch_async時,會創(chuàng)建多個線程,操作無序執(zhí)行。但是如果隊列錢有其他任務(wù),會等待其他任務(wù)執(zhí)行完成后再執(zhí)行其他的任務(wù)。適合的操作為:既不影響主線程,又不需要順序執(zhí)行的操作。

然后,我們再把操作改為dispatch_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}

可以看出,無論隊列的方式是串行隊列還是并行隊列,dispatch_sync同步操作方式都是不會創(chuàng)建新線程的,任務(wù)只會在主線程中執(zhí)行。

三、dispatch_get_global_queue():全局隊列

看下面一段代碼:
- (void) globalQueue
{
//全局隊列,都在主線程中執(zhí)行,不會死鎖,
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)}

全局隊列是系統(tǒng)的,無序創(chuàng)建,直接用即可,可以看出,全局隊列與并行隊列類型,但是調(diào)試時,無法確認操作所在隊列。
當(dāng)操作方式為dispatch_sync時,不再做解析,雷同上面。

四、dispatch_get_main_queue():主隊列

看下面一段代碼:

- (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}

每一個應(yīng)用程序中只有一個主隊列,直接使用即可無需創(chuàng)建,常常在主隊列中更新UI。主隊列中的操作都應(yīng)該自主隊列中執(zhí)行,不存在異步的概念。除非主線程被用戶殺掉,否則永遠不會結(jié)束。

五、dispatch_sync的應(yīng)用場景(登陸操作)。dispatch_sync會阻塞并行隊列的執(zhí)行,要求某一操作執(zhí)行完成之后才會執(zhí)行下一個操作。
- (void) newThread
{
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_CONCURRENT);
__block BOOL logon = NO;
dispatch_sync(q, ^{ //同步
    NSLog(@"模擬耗時操作 %@", [NSThread currentThread]);
    [NSThread sleepForTimeInterval:2.0f];//停留兩秒鐘,模仿耗時操作
    NSLog(@"模擬耗時完成 %@", [NSThread currentThread]);
    logon = YES;
});

dispatch_async(q, ^{
    NSLog(@"登錄完成的處理 %@", [NSThread currentThread]);
});
}

結(jié)果:

2016-04-14 10:47:24.117 test[26976:1276763] 模擬耗時操作 <NSThread: 0x7fe3a8d054e0>{number = 1, name = main}
2016-04-14 10:47:26.119 test[26976:1276763] 模擬耗時完成 <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,在并行隊列中等待前面的操作執(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)有多個任務(wù)時,可以把多個任務(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ù)。

看完這篇文章,相信大家對GCD有了詳細的了解,有問題歡迎大家一起探討,下班回家吃飯去,哈哈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 簡介 GCD(Grand Central Dispatch)是在macOS10.6提出來的,后來在iOS4.0被引...
    sunmumu1222閱讀 955評論 0 2
  • iOS中GCD的使用小結(jié) 作者dullgrass 2015.11.20 09:41*字?jǐn)?shù) 4996閱讀 20199...
    DanDanC閱讀 1,290評論 0 0
  • 目錄(GCD): 關(guān)鍵詞 混淆點 場景應(yīng)用 總結(jié) 1. 關(guān)鍵詞 線程概念: 獨立執(zhí)行的代碼段,一個線程同時間只能執(zhí)...
    Ryan___閱讀 1,369評論 0 3
  • 本篇博客共分以下幾個模塊來介紹GCD的相關(guān)內(nèi)容: 多線程相關(guān)概念 多線程編程技術(shù)的優(yōu)缺點比較? GCD中的三種隊列...
    有夢想的老伯伯閱讀 1,088評論 0 4
  • 1. GCD簡介 什么是GCD呢?我們先來看看百度百科的解釋簡單了解下概念 引自百度百科:Grand Centra...
    千尋_544f閱讀 501評論 0 0

友情鏈接更多精彩內(nèi)容