国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計(jì) > 正文

iOS多線程中,隊(duì)列和執(zhí)行的排列組合結(jié)果分析

2019-11-14 19:32:06
字體:
供稿:網(wǎng)友

本文是對(duì)以往學(xué)習(xí)的多線程中知識(shí)點(diǎn)的一個(gè)整理。

多線程中的隊(duì)列有:串行隊(duì)列,并發(fā)隊(duì)列,全局隊(duì)列,主隊(duì)列

執(zhí)行的方法有:同步執(zhí)行和異步執(zhí)行。那么兩兩一組合會(huì)有哪些注意事項(xiàng)呢?

如果不是在董鉑然博客園看到這邊文章請(qǐng) 點(diǎn)擊查看原文

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

其中phtread是跨平臺(tái)的。GCD和NSOperation都是常用的,后者是基于前者的。

但是兩者區(qū)別:GCD的核心概念是將一個(gè)任務(wù)添加到隊(duì)列,指定任務(wù)執(zhí)行的方法,然后執(zhí)行。 NSOperation則是直接將一個(gè)操作添加到隊(duì)列中。

為了整體結(jié)構(gòu)更加清晰,我是用GCD來做此排列組合的實(shí)驗(yàn)。實(shí)驗(yàn)主要是通過循環(huán)內(nèi)打印和主線程的打印先后順序來判斷結(jié)果,最后再加以總結(jié)

1.串行隊(duì)列,同步執(zhí)行

    dispatch_queue_t q = dispatch_queue_create("dantesx", NULL);        // 執(zhí)行任務(wù)    for (int i = 0; i<10; i++) {        dispatch_sync(q, ^{            NSLog(@"%@ %d", [NSThread currentThread], i);        });    }        NSLog(@"董鉑然 come here");

運(yùn)行效果:

 

執(zhí)行結(jié)果可以清楚的看到全在主線程執(zhí)行,并且是按照數(shù)序執(zhí)行,循環(huán)結(jié)束之后主線程的打印才輸出。

2.串行隊(duì)列,異步執(zhí)行

    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");

 運(yùn)行結(jié)果

結(jié)果顯示,系統(tǒng)開了1條異步線程,因此全部在線程2執(zhí)行,并且是順序執(zhí)行。主線程打印雖然在最上面,但是這個(gè)先后順序是不確定,如果睡個(gè)0.001秒,主線程的打印會(huì)混在中間。

3.并發(fā)隊(duì)列,異步執(zhí)行

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

 運(yùn)行結(jié)果

結(jié)果顯示,主線程的打印還是混在中間不確定的,因?yàn)楫惒骄€程就是誰也不等誰。系統(tǒng)開了多條線程,并且執(zhí)行的順序也是亂序的

 

4.并發(fā)隊(duì)列,同步執(zhí)行

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

 運(yùn)行結(jié)果

這個(gè)運(yùn)行結(jié)果和第1種的串行隊(duì)列,同步執(zhí)行是一模一樣的。 因?yàn)橥饺蝿?wù)的概念就是按順序執(zhí)行,后面都要等。言外之意就是不允許多開線程。 同步和異步則是決定開一條還是開多條。

所以一旦是同步執(zhí)行,前面什么隊(duì)列已經(jīng)沒區(qū)別了

5.主隊(duì)列,異步執(zhí)行

    // 1. 主隊(duì)列 - 程序啟動(dòng)之后已經(jīng)存在主線程,主隊(duì)列同樣存在    dispatch_queue_t q = dispatch_get_main_queue();    // 2. 安排一個(gè)任務(wù)    for (int i = 0; i<10; i++) {        dispatch_async(q, ^{            NSLog(@"%@ %d", [NSThread currentThread], i);        });    }    NSLog(@"睡會(huì)");    [NSThread sleepForTimeInterval:2.0];    NSLog(@"董鉑然 come here");

 運(yùn)行結(jié)果

結(jié)果顯示有點(diǎn)出人意料。主線程在睡會(huì)之后才打印,循環(huán)一直在等著。因?yàn)橹麝?duì)列的任務(wù)雖然會(huì)加到主線程中執(zhí)行,但是如果主線程里也有任務(wù)就必須等主線程任務(wù)執(zhí)行完才輪到主隊(duì)列的。

6.主隊(duì)列,同步執(zhí)行

    dispatch_queue_t q = dispatch_get_main_queue();        NSLog(@"卡死了嗎?");        dispatch_sync(q, ^{        NSLog(@"我來了");    });        NSLog(@"董鉑然 come here");

 運(yùn)行結(jié)果為卡死

卡死的原因是循環(huán)等待,主隊(duì)列的東西要等主線程執(zhí)行完,而因?yàn)槭峭綀?zhí)行不能開線程,所以下面的任務(wù)要等上面的任務(wù)執(zhí)行完,所以卡死。這是排列組合中唯一一個(gè)會(huì)卡死的組合。

7.同步任務(wù)的使用場景

    dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);    // 1. 用戶登錄,必須要第一個(gè)執(zhí)行    dispatch_sync(q, ^{        [NSThread sleepForTimeInterval:2.0];        NSLog(@"用戶登錄 %@", [NSThread currentThread]);    });    // 2. 扣費(fèi)    dispatch_async(q, ^{        NSLog(@"扣費(fèi) %@", [NSThread currentThread]);    });    // 3. 下載    dispatch_async(q, ^{        NSLog(@"下載 %@", [NSThread currentThread]);    });    NSLog(@"董鉑然 come here");

 運(yùn)行結(jié)果

結(jié)果顯示,“用戶登陸”在主線程打印,后兩個(gè)在異步線程打印。上面的“用戶登陸”使用同步執(zhí)行,后面的扣費(fèi)和下載都是異步執(zhí)行。所以“用戶登陸”必須第一個(gè)打印出來不管等多久,然后后面的兩個(gè)異步和主線程打印會(huì)不確定順序的打印。這就是日常開發(fā)中,那些后面對(duì)其有依賴的必須要先執(zhí)行的任務(wù)使用同步執(zhí)行,然后反正都要執(zhí)行先后順序無所謂的使用異步執(zhí)行。

8.block異步任務(wù)包裹同步任務(wù)

    dispatch_queue_t q = dispatch_queue_create("dantesx", DISPATCH_QUEUE_CONCURRENT);    void (^task)() = ^ {        // 1. 用戶登錄,必須要第一個(gè)執(zhí)行        dispatch_sync(q, ^{            NSLog(@"用戶登錄 %@", [NSThread currentThread]);        });        // 2. 扣費(fèi)        dispatch_async(q, ^{            NSLog(@"扣費(fèi) %@", [NSThread currentThread]);        });        // 3. 下載        dispatch_async(q, ^{                        NSLog(@"下載 %@", [NSThread currentThread]);        });    };        dispatch_async(q, task);    [NSThread sleepForTimeInterval:1.0];    NSLog(@"董鉑然 come here");

 運(yùn)行結(jié)果

因?yàn)檎麄€(gè)block是在異步執(zhí)行的,所以即使里面“用戶登陸”是同步執(zhí)行,那也無法在主線程中執(zhí)行,只能開一條異步線程執(zhí)行,因?yàn)槭峭降乃员仨毜人葓?zhí)行,后面的“扣費(fèi)”和“下載”在上面同步執(zhí)行結(jié)束之后,不確定順序的打印。

9.全局隊(duì)列

    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");

 運(yùn)行結(jié)果

全局隊(duì)列的本質(zhì)就是并發(fā)隊(duì)列,只是在后面加入了,“服務(wù)質(zhì)量”,和“調(diào)度優(yōu)先級(jí)” 兩個(gè)參數(shù),這兩個(gè)參數(shù)一般為了系統(tǒng)間的適配,最好直接填0和0

如果不是在董鉑然博客園看到這邊文章請(qǐng) 點(diǎn)擊查看原文

總結(jié):

1. 開不開線程,取決于執(zhí)行任務(wù)的函數(shù),同步不開,異步開。

2. 開幾條線程,取決于隊(duì)列,串行開一條,并發(fā)開多條(異步)

3. 主隊(duì)列:  專門用來在主線程上調(diào)度任務(wù)的"隊(duì)列",主隊(duì)列不能在其他線程中調(diào)度任務(wù)!

4. 如果主線程上當(dāng)前正在有執(zhí)行的任務(wù),主隊(duì)列暫時(shí)不會(huì)調(diào)度任務(wù)的執(zhí)行!主隊(duì)列同步任務(wù),會(huì)造成死鎖。原因是循環(huán)等待

5. 同步任務(wù)可以隊(duì)列調(diào)度多個(gè)異步任務(wù)前,指定一個(gè)同步任務(wù),讓所有的異步任務(wù),等待同步任務(wù)執(zhí)行完成,這是依賴關(guān)系。

6. 全局隊(duì)列:并發(fā),能夠調(diào)度多個(gè)線程,執(zhí)行效率高,但是相對(duì)費(fèi)電。 串行隊(duì)列效率較低,省電省流量,或者是任務(wù)之間需要依賴也可以使用串行隊(duì)列。

7. 也可以通過判斷當(dāng)前用戶的網(wǎng)絡(luò)環(huán)境來決定開的線程數(shù)。WIFI下6條,3G/4G下2~3條。


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 上虞市| 梁平县| 山阳县| 济南市| 潜江市| 武功县| 哈尔滨市| 永兴县| 晋中市| 石首市| 新营市| 九江市| 古蔺县| 柯坪县| 满城县| 襄汾县| 富川| 乌鲁木齐县| 崇礼县| 桃园市| 六盘水市| 城口县| 同德县| 内乡县| 育儿| 周宁县| 黔西| 新安县| 富源县| 呼和浩特市| 晋宁县| 伊川县| 龙南县| 剑阁县| 夹江县| 张家口市| 新兴县| 游戏| 吉林省| 饶平县| 台江县|