iOS多線程中,隊列和執行的排列組合結果分析,ios多線程

來源:互聯網
上載者:User

iOS多線程中,隊列和執行的排列組合結果分析,ios多線程

本文是對以往學習的多線程中知識點的一個整理。

多線程中的隊列有:串列隊列,並發隊列,全域隊列,主隊列

執行的方法有:同步執行和非同步執行。那麼兩兩一組合會有哪些注意事項呢?

如果不是在董鉑然部落格園看到這邊文章請 點擊查看原文

提到多線程,也就是四種,pthread,NSthread,GCD,NSOperation  

其中phtread是跨平台的。GCD和NSOperation都是常用的,後者是基於前者的。

但是兩者區別:GCD的核心概念是將一個任務添加到隊列,指定任務執行的方法,然後執行。 NSOperation則是直接將一個操作添加到隊列中。

為了整體結構更加清晰,我是用GCD來做此排列組合的實驗。實驗主要是通過迴圈內列印和主線程的列印先後順序來判斷結果,最後再加以總結

1.串列隊列,同步執行
    dispatch_queue_t q = dispatch_queue_create("dantesx", NULL);        // 執行任務    for (int i = 0; i<10; i++) {        dispatch_sync(q, ^{            NSLog(@"%@ %d", [NSThread currentThread], i);        });    }        NSLog(@"董鉑然 come here");

運行效果:

 

執行結果可以清楚的看到全在主線程執行,並且是按照數序執行,迴圈結束之後主線程的列印才輸出。

2.串列隊列,非同步執行
    dispatch_queue_t q = dispatch_queue_create("dantesx", NULL);        for (int i = 0; i<10; i++) {        dispatch_async(q, ^{            NSLog(@"%@ %d", [NSThread currentThread], i);        });    }    //    [NSThread sleepForTimeInterval:0.001];    NSLog(@"董鉑然 come here");

 運行結果

結果顯示,系統開了1條非同步線程,因此全部線上程2執行,並且是順序執行。主線程列印雖然在最上面,但是這個先後順序是不確定,如果睡個0.001秒,主線程的列印會混在中間。

3.並發隊列,非同步執行
    // 1. 隊列    dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);        // 2. 非同步執行    for (int i = 0; i<10; i++) {        dispatch_async(q, ^{            NSLog(@"%@ %d", [NSThread currentThread], i);        });    }    //    [NSThread sleepForTimeInterval:2.0];    NSLog(@"董鉑然 come here");

 運行結果

結果顯示,主線程的列印還是混在中間不確定的,因為非同步線程就是誰也不等誰。系統開了多條線程,並且執行的順序也是亂序的

 

4.並發隊列,同步執行
    // 1. 隊列    dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);        // 2. 同步執行    for (int i = 0; i<10; i++) {        dispatch_sync(q, ^{            NSLog(@"%@ %d", [NSThread currentThread], i);        });    }    //    [NSThread sleepForTimeInterval:2.0];    NSLog(@"董鉑然 come here");

 運行結果

這個運行結果和第1種的串列隊列,同步執行是一模一樣的。 因為同步任務的概念就是按順序執行,後面都要等。言外之意就是不允許多開線程。 同步和非同步則是決定開一條還是開多條。

所以一旦是同步執行,前面什麼隊列已經沒區別了。

5.主隊列,非同步執行
    // 1. 主隊列 - 程式啟動之後已經存在主線程,主隊列同樣存在    dispatch_queue_t q = dispatch_get_main_queue();    // 2. 安排一個任務    for (int i = 0; i<10; i++) {        dispatch_async(q, ^{            NSLog(@"%@ %d", [NSThread currentThread], i);        });    }    NSLog(@"睡會");    [NSThread sleepForTimeInterval:2.0];    NSLog(@"董鉑然 come here");

 運行結果

結果顯示有點出人意料。主線程在睡會之後才列印,迴圈一直在等著。因為主隊列的任務雖然會加到主線程中執行,但是如果主線程裡也有任務就必須等主線程任務執行完才輪到主隊列的。

6.主隊列,同步執行
    dispatch_queue_t q = dispatch_get_main_queue();        NSLog(@"卡死了嗎?");        dispatch_sync(q, ^{        NSLog(@"我來了");    });        NSLog(@"董鉑然 come here");

 運行結果為卡死

卡死的原因是迴圈等待,主隊列的東西要等主線程執行完,而因為是同步執行不能開線程,所以下面的任務要等上面的任務執行完,所以卡死。這是排列組合中唯一一個會卡死的組合。

7.同步任務的使用情境
    dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);    // 1. 使用者登入,必須要第一個執行    dispatch_sync(q, ^{        [NSThread sleepForTimeInterval:2.0];        NSLog(@"使用者登入 %@", [NSThread currentThread]);    });    // 2. 計費    dispatch_async(q, ^{        NSLog(@"計費 %@", [NSThread currentThread]);    });    // 3. 下載    dispatch_async(q, ^{        NSLog(@"下載 %@", [NSThread currentThread]);    });    NSLog(@"董鉑然 come here");

 運行結果

結果顯示,“使用者登陸”在主線程列印,後兩個在非同步線程列印。上面的“使用者登陸”使用同步執行,後面的計費和下載都是非同步執行。所以“使用者登陸”必須第一個列印出來不管等多久,然後後面的兩個非同步和主線程列印會不確定順序的列印。這就是日常開發中,那些後面對其有依賴的必須要先執行的任務使用同步執行,然後反正都要執行先後順序無所謂的使用非同步執行。

8.block非同步任務包裹同步任務
    dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);    void (^task)() = ^ {        // 1. 使用者登入,必須要第一個執行        dispatch_sync(q, ^{            NSLog(@"使用者登入 %@", [NSThread currentThread]);        });        // 2. 計費        dispatch_async(q, ^{            NSLog(@"計費 %@", [NSThread currentThread]);        });        // 3. 下載        dispatch_async(q, ^{                        NSLog(@"下載 %@", [NSThread currentThread]);        });    };        dispatch_async(q, task);    [NSThread sleepForTimeInterval:1.0];    NSLog(@"董鉑然 come here");

 運行結果

因為整個block是在非同步執行的,所以即使裡面“使用者登陸”是同步執行,那也無法在主線程中執行,只能開一條非同步線程執行,因為是同步的所以必須等他先執行,後面的“計費”和“下載”在上面同步執行結束之後,不確定順序的列印。

9.全域隊列
    dispatch_queue_t q = dispatch_get_global_queue(0, 0);        for (int i = 0; i < 10; i++) {        dispatch_async(q, ^{            NSLog(@"%@ %d", [NSThread currentThread], i);        });    }    [NSThread sleepForTimeInterval:1.0];    NSLog(@"com here");

 運行結果

全域隊列的本質就是並發隊列,只是在後面加入了,“服務品質”,和“調度優先順序” 兩個參數,這兩個參數一般為了系統間的適配,最好直接填0和0。

如果不是在董鉑然部落格園看到這邊文章請 點擊查看原文

總結:

1. 開不開線程,取決於執行任務的函數,同步不開,非同步開。

2. 開幾條線程,取決於隊列,串列開一條,並發開多條(非同步)

3. 主隊列:  專門用來在主線程上調度任務的"隊列",主隊列不能在其他線程中調度任務!

4. 如果主線程上當前正在有執行的任務,主隊列暫時不會調度任務的執行!主隊列同步任務,會造成死結。原因是迴圈等待

5. 同步任務可以隊列調度多個非同步任務前,指定一個同步任務,讓所有的非同步任務,等待同步任務執行完成,這是依賴關係。

6. 全域隊列:並發,能夠調度多個線程,執行效率高,但是相對費電。 串列隊列效率較低,省電省流量,或者是任務之間需要依賴也可以使用串列隊列。

7. 也可以通過判斷目前使用者的網路環境來決定開的線程數。WIFI下6條,3G/4G下2~3條。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.