多線程GCD的使用

         GCD——Grand Central Dispatch 是基於C語言的框架,能夠充分利用多核,也是蘋果官方推薦使用的多線程技術。程序員

 

         GCD是由蘋果開發的一個多核編程的解決方案。iOS4.0+才能使用,是替代NSThread,NSOperation的高效和強大的技術,GCD是基於C語言的

         GCD是蘋果公司爲多核的並行運算提出的解決方案編程

         GCD會自動利用更多的CPU內核(好比雙核、四核)多線程

         GCD會自動管理線程的生命週期(建立線程、調度任務、銷燬線程)併發

程序員只須要告訴GCD想要執行什麼任務,不須要編寫任何線程管理代碼
 
多線程裏面概念性的東西不少也很難記,因此必定要好好理解。仍是經過代碼,在溫習溫習吧。相同的代碼寫屢次,雖然有時很枯燥,可每次都會有不一樣的體會和領悟。走起!
viewController中:
 1 #import "ViewController.h"
 2 
 3 @interface ViewController ()
 4 
 5 @end
 6 
 7 @implementation ViewController
 8 
 9 /*
10 //寫以前,再來溫習溫習。
11  GCD的使用:
12  一 :隊列
13  1.串行隊列:添加到隊列中的任務是一個一個執行的
14  2.併發(行)隊列:添加到隊列中的任務是多個同時執行的
15  3.主隊列:裏面的任務都是在主線程執行的。
16  4.全局隊列:並行(發)隊列
17  
18  二:同步、異步
19  一、同步:須要後面的任務等待,不會開啓新的線程,會直接使用當前的線程
20  
21  二、異步:不須要後面的任務等待,會開啓新的線程
22  */
23 
24 - (void)viewDidLoad {
25     [super viewDidLoad];
26     
27     /*---------建立併發隊列---------*/
28 
29     //1.建立並行隊列
30     dispatch_queue_t queue1 = dispatch_queue_create("queue1", DISPATCH_QUEUE_CONCURRENT);
31     
32     //2.獲取全局隊列(並行隊列)
33     /*優先級<#long identifier#>
34      DISPATCH_QUEUE_PRIORITY_HIGH
35      DISPATCH_QUEUE_PRIORITY_DEFAULT
36      DISPATCH_QUEUE_PRIORITY_LOW
37      DISPATCH_QUEUE_PRIORITY_BACKGROUND
38      */
39     
40     dispatch_queue_t queue2 = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
41     
42     //(1)在併發隊列添加異步任務
43 
44     dispatch_async(queue2, ^{
45     
46                   for (int i = 0; i < 50 ;i ++) {
47                 
48                 NSLog(@"1---------1");
49             }
50         
51         
52     });
53     
54     dispatch_async(queue2, ^{
55         
56         
57             for (int i = 0; i < 50 ;i ++) {
58                 
59                 NSLog(@"2---------2");
60             }
61         
62         
63     });

打印結果:框架

 

經過打印結果咱們能夠看出:
(1)併發隊列異步添加任務會開多條線程,執行順序是沒有前後(同時執行)
 
看完併發隊列的異步添加,讓咱們再來看看併發隊列的同步添加:

 

 1 dispatch_sync(queue2, ^{
 2     
 3         @autoreleasepool {
 4             for (int i = 0; i < 50 ;i ++) {
 5                 
 6                 NSLog(@"1---------1");
 7             }
 8         }
 9     });
10     
11     
12     dispatch_sync(queue2, ^{
13         
14         @autoreleasepool {
15             for (int i = 0; i < 50 ;i ++) {
16                 
17                 NSLog(@"2---------2");
18             }
19         }
20     });

這個打印結果相信不用說,咱們都知道確定是先執行1  在執行2異步

其實執行問題好回答,關鍵是此時的任務是在那個線程完成的,相信若是你對同步添加的概念若是十分清楚的話必定能回答對,沒有錯。這些任務是在主線程中完成的。並非在queue2中完成的。讓咱們看圖吧,有圖有真相
經過以上分析咱們能夠看出:
(1)在併發隊列中同步添加任務,不會開啓新的線程,會直接使用當前線程,
(2)而且,咱們添加的任務是添加到主線程。並非表面現象的queue2。
 
 
看完併發(行)隊列,讓咱們來看看串行隊列吧。
 1     /*---------建立串行----------*/
 2     
 3     dispatch_queue_t queue = dispatch_queue_create("queue3", DISPATCH_QUEUE_SERIAL);
 4     
 5     //向串行隊列異步添加任務
 6     dispatch_async(queue, ^{
 7     
 8         for (int i=0; i<50; i++) {
 9             NSLog(@"🐷....i:%d",i);
10         }
11 
12     });
13     
14     dispatch_async(queue, ^{
15     
16         for (int i=0; i<50; i++) {
17             NSLog(@"🐶....i:%d",i);
18         }
19 
20     });

打印結果:async

 儘管是異步添加任務,可是該隊列是串行隊列,因此豬 先被執行,而後才執行狗。ide

若是此時咱們再在viewDidLoad中也就是在狗的for訓話下面添加一個for循環的話你能想象出結果嗎?spa

1     for (int i=0; i<100; i++) {
2         NSLog(@"🐱....i:%d",i);
3     }

打印結果:線程

不難看出貓與(狗和豬)是同時執行的。而(豬和狗)則是豬先執行,狗在執行。例如豬和狗排了一個隊,而貓本身排了一個隊。
 
繼續介紹:

向串行隊列同步添加任務

    dispatch_sync(queue, ^{
        
        for (int i=0; i<50; i++) {
            NSLog(@"🐶....i:%d",i);
        }
    });
    
    dispatch_sync(queue, ^{
    
        for (int i=0; i<100; i++) {
            NSLog(@"🐱....i:%d",i);
        }
        
    });
    
    for (int i=0; i<100; i++) {
        NSLog(@"🐷....i:%d",i);
    }

 運行結果毫無疑問。狗-----》貓----------》豬;時刻記着同步添加任務,不會開啓新的線程,會直接使用當前線程。那麼確定這三個任務也是在當前的主線程。

 

介紹完這些,還有一個重要的東西那就是死鎖

讓咱們來看一下

獲取主隊列:

    dispatch_queue_t mainQueue = dispatch_get_main_queue();

分配任務:

1     NSLog(@"任務開始啦!!!");
2     //同步添加任務
3     dispatch_sync(mainQueue, ^{
4     
5         NSLog(@"任務添加");
6         
7     });
8     
9     NSLog(@"結束");

毫無疑問第一個打印確定是  第一行的「任務開始啦!!!」,那麼接下來走第三行代碼,由於是Block因此第五行的代碼要在第九行的打印執行結束後才能被執行(block回調),又由於是同步添加任務,因此第九行代碼要在上面的任務執行完才能開始。因此編譯器猶豫不知道該執行那一個。會形成死鎖。

打印結果:

 

總結:(1)在使用主隊列時,絕對不能夠在主隊列中同步添加任務,會形成死鎖。

         (2)併發隊列:同步添加不會開啓新的線程,異步添加會開啓多條線程。

         (3)串行隊列:同步添加不會開啓新的線程,異步添加會開啓一條線程。

         (4)由(2)和(3)得出結論同步添加任務,不具有開啓線程的能力。異步添加任務開啓線程的條數由當前隊列決定,串行隊列開啓一條線程,並行隊列開啓多條。

相關文章
相關標籤/搜索