串行 并行 同步 異步的執(zhí)行順序

串行隊(duì)列、并行隊(duì)列、同步、異步是gcd編程中四個(gè)非常重要的概念,它們的組合會(huì)產(chǎn)生多種不同的執(zhí)行順序,在本文,我主要通過代碼來羅列一下所有的可能產(chǎn)生的結(jié)果,并根據(jù)執(zhí)行結(jié)果總結(jié)一下gcd編程的一些特點(diǎn)。

(1)串行隊(duì)列 異步任務(wù)

-(void)test{

dispatch_queue_tq = dispatch_queue_create("fs", DISPATCH_QUEUE_SERIAL);

NSLog(@"start--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_async(q, ^{

NSLog(@"async--%@",[NSThreadcurrentThread]);

});

}

NSLog(@"end--%@",[NSThreadcurrentThread]);

}

打印結(jié)果:

上面代碼創(chuàng)建了一個(gè)串行隊(duì)列,然后往串行隊(duì)列中添加了10個(gè)異步任務(wù),從打印結(jié)果可以看出:先在主線程中執(zhí)行打印start—,然后將異步任務(wù)添加到串行隊(duì)列中(只是添加,并沒有立即執(zhí)行),之后在主線程打印end—,最后才會(huì)從串行隊(duì)列中依次取出一個(gè)任務(wù),并在子線程中執(zhí)行,因此異步任務(wù)打印是有序的。所以, 主線程會(huì)在執(zhí)行完dispatch_async方法后,立即返回執(zhí)行主線程后續(xù)相關(guān)操作,主線程任務(wù)執(zhí)行完畢后,才會(huì)在子線程中依次執(zhí)行異步任務(wù)。由于串行隊(duì)列中的任務(wù)是依次取出來執(zhí)行的,即前一個(gè)任務(wù)在子線程執(zhí)行完畢后,才能取出后一個(gè)任務(wù)來執(zhí)行,所以只需要?jiǎng)?chuàng)建一個(gè)子線程即可。

結(jié)論:串行隊(duì)列 異步任務(wù),會(huì)創(chuàng)建子線程,且只創(chuàng)建一個(gè)子線程,異步任務(wù)執(zhí)行是有序的

(2)串行隊(duì)列 同步任務(wù)

-(void)test2{

dispatch_queue_tq = dispatch_queue_create("fs", DISPATCH_QUEUE_SERIAL);

NSLog(@"start--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_sync(q, ^{

NSLog(@"sync--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end--%@",[NSThreadcurrentThread]);

}

打印結(jié)果:

上面代碼創(chuàng)建了一個(gè)串行隊(duì)列,然后往串行隊(duì)列中添加了10個(gè)同步任務(wù),從打印結(jié)果可以看出:先在主線程中執(zhí)行打印start—,然后在主線程依次打印同步任務(wù),最后在主線程打印end—。所以,主線程在執(zhí)行dispatch_sync方法后,并沒有立刻返回,而是阻塞了當(dāng)前線程,去等待dispatch_sync方法里面的block執(zhí)行完畢,等到for循環(huán)里面所有同步任務(wù)執(zhí)行完畢后,才返回去執(zhí)行后面的end—的打印操作,所有的打印都是在主線程完成。

結(jié)論: 串行隊(duì)列 同步任務(wù),不創(chuàng)建新線程,同步任務(wù)執(zhí)行是有序的。

問題:細(xì)心的你可能發(fā)現(xiàn)一個(gè)問題:既然阻塞了當(dāng)前線程(主線程),為什么同步任務(wù)里面的block還能在主線程中打?。?a href="http://www.lxweimin.com/writer#/notebooks/5356277/notes/13012892" target="_blank">請(qǐng)點(diǎn)這里。

(3)并行隊(duì)列 異步任務(wù)

-(void)test3{

dispatch_queue_tq = dispatch_queue_create("fs", DISPATCH_QUEUE_CONCURRENT);

NSLog(@"start--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_async(q, ^{

NSLog(@"async--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end--%@",[NSThreadcurrentThread]);

}

打印結(jié)果:

上面代碼創(chuàng)建了一個(gè)并行隊(duì)列,然后往串行隊(duì)列中添加了10個(gè)異步任務(wù),從打印結(jié)果可以看出:先在主線程中執(zhí)行打印start—,然后將異步任務(wù)添加到并行隊(duì)列中(只是添加,并沒有立即執(zhí)行),之后立刻返回,在主線程打印end—,最后才會(huì)從并行隊(duì)列中依次取出多個(gè)任務(wù),并創(chuàng)建多個(gè)子線程來執(zhí)行(至于創(chuàng)建幾個(gè)子線程由系統(tǒng)決定),由于每個(gè)任務(wù)執(zhí)行時(shí)間不同,子線程獲得CPU的時(shí)間也不同,所以異步任務(wù)打印結(jié)果的順序也不同,而且每次打印的同步任務(wù)結(jié)果都不一樣。

結(jié)論:并行隊(duì)列 異步任務(wù) 創(chuàng)建子線程,且可以是多個(gè)子線程,異步任務(wù)打印結(jié)果無序。

(4)并行隊(duì)列 同步任務(wù)

-(void)test4{

dispatch_queue_tq = dispatch_queue_create("fs", DISPATCH_QUEUE_CONCURRENT);

NSLog(@"start--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_sync(q, ^{

NSLog(@"sync--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end--%@",[NSThreadcurrentThread]);

}

打印結(jié)果:

上面代碼創(chuàng)建了一個(gè)并行隊(duì)列,然后往串行隊(duì)列中添加了10個(gè)同步任務(wù),從打印結(jié)果可以看出:先在主線程中執(zhí)行打印start—,然后在主線程依次打印同步任務(wù),最后在主線程打印end—。所以,主線程在執(zhí)行dispatch_sync方法后,并沒有立刻返回,而是阻塞了當(dāng)前線程,去等待dispatch_sync方法里面的block執(zhí)行完畢,等到for循環(huán)里面所有同步任務(wù)執(zhí)行完畢后,才返回去執(zhí)行后面的end—的打印操作,所有的打印都是在主線程完成。

結(jié)論: 并行隊(duì)列 同步任務(wù),不創(chuàng)建新線程,同步任務(wù)執(zhí)行是有序的。

總結(jié)上面的四種情況得出結(jié)論:

(1)同步、異步?jīng)Q定是否創(chuàng)建子線程,同步任務(wù)不創(chuàng)建子線程,都是在主線程中執(zhí)行,異步任務(wù)創(chuàng)建子線程。

(2)串行、并行決定創(chuàng)建子線程的個(gè)數(shù),串行創(chuàng)建一個(gè)子線程,并行可創(chuàng)建多個(gè)子線程(具體幾個(gè)由系統(tǒng)決定)。

下面來點(diǎn)稍微復(fù)雜的情況:

(5)串行隊(duì)列中先異步再同步

-(void)test5{

dispatch_queue_tq = dispatch_queue_create("fs", DISPATCH_QUEUE_SERIAL);

NSLog(@"start--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_async(q, ^{

NSLog(@"async--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end1--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_sync(q, ^{

NSLog(@"sync--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end2--%@",[NSThreadcurrentThread]);

}

打印結(jié)果:

上面代碼創(chuàng)建了一個(gè)串行隊(duì)列,然后往串行隊(duì)列中添加了10個(gè)異步任務(wù),再添加10個(gè)同步任務(wù),從打印結(jié)果可以看出:先在主線程中執(zhí)行打印start—,然后將異步任務(wù)添加到串行隊(duì)列中(只是添加,并沒有立即執(zhí)行),之后在主線程打印end1—,再然后往串行隊(duì)列里添加了1個(gè)同步任務(wù),此時(shí)主線程堵塞,等待串行隊(duì)列里地同步任務(wù)執(zhí)行完畢。此時(shí)創(chuàng)建一個(gè)子線程開始依次執(zhí)行異步任務(wù),異步任務(wù)結(jié)束后,在主線程中執(zhí)行同步任務(wù)(上面的結(jié)論)。1個(gè)同步任務(wù)執(zhí)行完后(此時(shí)串行隊(duì)列里沒有任務(wù)了),主線程返回,for循環(huán)繼續(xù)往串行隊(duì)列里添加1個(gè)同步任務(wù),此時(shí)主線程繼續(xù)阻塞,等待串行隊(duì)列里同步任務(wù)執(zhí)行完畢,此時(shí)主線程執(zhí)行這個(gè)同步任務(wù),執(zhí)行完畢后,主線程返回繼續(xù)for循環(huán)……。等for循環(huán)結(jié)束后,最后在主線程執(zhí)行打印end2—的操作。

(6)串行隊(duì)列中先同步再異步

-(void)test6{

dispatch_queue_tq = dispatch_queue_create("fs", DISPATCH_QUEUE_SERIAL);

NSLog(@"start--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_sync(q, ^{

NSLog(@"sync--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end1--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_async(q, ^{

NSLog(@"async--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end2--%@",[NSThreadcurrentThread]);

}

打印結(jié)果:

上面代碼創(chuàng)建了一個(gè)串行隊(duì)列,然后往串行隊(duì)列中添加了10個(gè)同步任務(wù),再添加10個(gè)異步任務(wù),從打印結(jié)果可以看出:先在主線程中執(zhí)行打印start—,然后往串行隊(duì)列里添加了1個(gè)同步任務(wù),此時(shí)主線程堵塞,等待串行隊(duì)列里地同步任務(wù)執(zhí)行完畢。此時(shí)創(chuàng)建一個(gè)子線程開始依次執(zhí)行串行隊(duì)列的任務(wù),在主線程中執(zhí)行同步任務(wù)(上面的結(jié)論)。1個(gè)同步任務(wù)執(zhí)行完后(此時(shí)串行隊(duì)列里沒有任務(wù)了),主線程返回,for循環(huán)繼續(xù)往串行隊(duì)列里添加1個(gè)同步任務(wù),此時(shí)主線程繼續(xù)阻塞,等待串行隊(duì)列里同步任務(wù)執(zhí)行完畢,此時(shí)主線程執(zhí)行這個(gè)同步任務(wù),執(zhí)行完畢后,主線程返回繼續(xù)for循環(huán)……。等for循環(huán)結(jié)束后,在主線程打印end1—,然后執(zhí)行到dispatch_async往串行隊(duì)列里添加異步任務(wù),并立即返回,for循環(huán)結(jié)束后,串行隊(duì)列里有10個(gè)異步任務(wù),此時(shí)主線程繼續(xù)往下執(zhí)行打印end2—的操作。之后開始創(chuàng)建子線程依次執(zhí)行串行隊(duì)列里地異步任務(wù)。

(7)并行隊(duì)列中先異步再同步

-(void)test7{

dispatch_queue_tq = dispatch_queue_create("fs", DISPATCH_QUEUE_CONCURRENT);

NSLog(@"start--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_async(q, ^{

NSLog(@"async--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end1--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_sync(q, ^{

NSLog(@"sync--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end2--%@",[NSThreadcurrentThread]);

}

打印結(jié)果:

上面代碼創(chuàng)建了一個(gè)并行隊(duì)列,然后往并行隊(duì)列中添加了10個(gè)異步任務(wù)和10個(gè)同步任務(wù),上面只是某一次的打印結(jié)果,每次的打印結(jié)果都不一樣,從打印結(jié)果可以看出:由于是并行隊(duì)列,會(huì)開啟多個(gè)子線程執(zhí)行異步任務(wù),所以異步任務(wù)的打印結(jié)果是無序的,而同步任務(wù)由于都是在主線程中執(zhí)行,所有總體是有序的。而且同步與異步任務(wù)是交叉著執(zhí)行完畢的。

(8)并行隊(duì)列中先同步再異步

-(void)test8{

dispatch_queue_tq = dispatch_queue_create("fs", DISPATCH_QUEUE_CONCURRENT);

NSLog(@"start--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_sync(q, ^{

NSLog(@"sync--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end1--%@",[NSThreadcurrentThread]);

for(inti=0; i<10; i++) {

dispatch_async(q, ^{

NSLog(@"async--%@---%d",[NSThreadcurrentThread],i);

});

}

NSLog(@"end2--%@",[NSThreadcurrentThread]);

}

打印結(jié)果:

上面代碼創(chuàng)建了一個(gè)并行隊(duì)列,然后往并行隊(duì)列中添加了10個(gè)同步任務(wù)和10個(gè)異步任務(wù),每次的打印結(jié)果也不一定一樣,從打印結(jié)果可以看出:都是先有序的執(zhí)行完同步任務(wù),再無序的執(zhí)行異步任務(wù)。沒有交叉執(zhí)行完的想象,原因在于先添加的同步任務(wù),沒添加一個(gè)同步任務(wù)會(huì)堵塞主線程,等待同步任務(wù)執(zhí)行完畢,所以會(huì)依次在主線程執(zhí)行同步任務(wù),for循環(huán)結(jié)束后,此時(shí)并行隊(duì)列里為空,之后再往并行隊(duì)列中添加了10個(gè)異步任務(wù),此時(shí)沒有堵塞主線程,主線程一直往下執(zhí)行打印end2—,此時(shí)開啟多個(gè)子線程來執(zhí)行執(zhí)行異步任務(wù),所以執(zhí)行完的順序是未知的。

以上是對(duì)GCD編程中串行、并行、同步、異步的執(zhí)行順序的一個(gè)簡(jiǎn)單分析,其中還留了一個(gè)問題,這個(gè)問題將在下一篇文章中給出答案,本篇主要是自定義的串并行隊(duì)列,下一篇主要分析一下ios系統(tǒng)給我們提供的一些隊(duì)列,最常用的是主隊(duì)列和全局隊(duì)列。



轉(zhuǎn)載自feisongfs

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容