ios - 多線程之七:GCD并行

接以上項目,我們開始 GCD 并行隊列的使用

創建按鈕入口

UIButton *btn4 = [UIButton buttonWithType:UIButtonTypeCustom];
btn4.frame = CGRectMake(40, 300, 100, 40);
[btn4 setTitle:@"GCD并行" forState:UIControlStateNormal];
[btn4 setBackgroundColor:[UIColor blueColor]];
[btn4 addTarget:self action:@selector(click_GCD_Parallel) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn4];

dispatch_get_global_queue

情況一:同步任務 + 全局隊列

可以在任務創建時,設置在隊列中的優先級

 /*
    //GCD - 并行隊列中任務的執行優先級
 *  - DISPATCH_QUEUE_PRIORITY_HIGH:         QOS_CLASS_USER_INITIATED
 *  - DISPATCH_QUEUE_PRIORITY_DEFAULT:      QOS_CLASS_DEFAULT
 *  - DISPATCH_QUEUE_PRIORITY_LOW:          QOS_CLASS_UTILITY
 *  - DISPATCH_QUEUE_PRIORITY_BACKGROUND:   QOS_CLASS_BACKGROUND
 */

dispatch_sync(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"開始子線程 :task1");
    for (int i = 10; i <= 20 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 20) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task1");
            });
        }
    }
});
dispatch_sync(dispatch_get_global_queue(-2, 0), ^{
    NSLog(@"開始子線程 :task2");
    for (int i = 20; i <= 30 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 30) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task2");
            });
        }
    }
});
dispatch_sync(dispatch_get_global_queue(2, 0), ^{
    NSLog(@"開始子線程 :task3");
    for (int i = 30; i <= 40 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 40) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task3");
            });
        }
    }
}); 

執行結果:

全局 + 同步

日志分析:
1:堵塞主線程;
2:系統不會開啟子線程;
3:所有的任務還是在主線程執行;
4:所有同步任務依次按照順序執行;
5:此時全局隊列的優先級起不到作用,任務依舊按照順序執行;

情況二 : 異步任務 + ?全局隊列

dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSLog(@"開始子線程 :task4");
    for (int i = 10; i <= 20 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 20) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task1");
            });
        }
    }
});
dispatch_async(dispatch_get_global_queue(-2, 0), ^{
    NSLog(@"開始子線程 :task5");
    for (int i = 20; i <= 30 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 30) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task2");
            });
        }
    }
});
dispatch_async(dispatch_get_global_queue(2, 0), ^{
    NSLog(@"開始子線程 :task6");
    for (int i = 30; i <= 40 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 40) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task3");
            });
        }
    }
});

執行結果:

全局 + 異步

日志分析:
1:不會堵塞主線程
2:會為每一個異步任務開啟一個子線程;
3:可以通過設置任務優先級控制任務的執行優先順序
4:充分證明全局隊列是并行隊列

自創建并行隊列

情況一:并行隊列 + 同步任務
創建并行隊列語句

 dispatch_queue_t queue_concurrent = dispatch_queue_create("queue.concurrent", DISPATCH_QUEUE_CONCURRENT);

代碼:

dispatch_sync(queue_concurrent, ^{
    NSLog(@"開始子線程 :task7");
    for (int i = 70; i <= 80 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 80) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task7");
            });
        }
    }
});

dispatch_sync(queue_concurrent, ^{
    NSLog(@"開始子線程 :task8");
    for (int i = 80; i <= 90 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 90) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task8");
            });
        }
    }
});

dispatch_sync(queue_concurrent, ^{
    NSLog(@"開始子線程 :task9");
    for (int i = 90; i <= 100 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 100) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task9");
            });
        }
    }
});

執行結果:

全局 + 同步

日志分析:
1:堵塞主線程
2:任務不會被開啟子線程;
3:所有同步任務在主線程中執行;
4:同步任務按照順序依次執行;

情況二:并行隊列 + 異步任務

 dispatch_queue_t queue_concurrent = dispatch_queue_create("queue.concurrent", DISPATCH_QUEUE_CONCURRENT);

dispatch_async(queue_concurrent, ^{
    NSLog(@"開始子線程 :task7");
    for (int i = 70; i <= 80 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 80) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task7");
            });
        }
    }
});

dispatch_async(queue_concurrent, ^{
    NSLog(@"開始子線程 :task8");
    for (int i = 80; i <= 90 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 90) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task8");
            });
        }
    }
});

dispatch_async(queue_concurrent, ^{
    NSLog(@"開始子線程 :task9");
    for (int i = 90; i <= 100 ; i ++) {
        sleep(1);
        NSLog(@"當前線程名稱:%@ ——%d",[NSThread currentThread].name,i);
        if (i == 100) {
            dispatch_async(dispatch_get_main_queue(), ^{
                NSLog(@"回到主線程,task9");
            });
        }
    }
});

執行結果:

并發隊列 + 異步任務

日志分析:
1:不會堵塞線程
2:系統會為每一個異步任務開始一個子線程;
3:每個異步任務在自己對應的線程中執行;
4:各個任務之間是并發執行的;

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容