精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

iOS從實(shí)際出發(fā)理解多線程

移動(dòng)開發(fā)
這篇文章從我剛開始構(gòu)思著去寫的時(shí)候,就希望自己能換個(gè)角度去寫,想從實(shí)際問(wèn)題出發(fā)總結(jié)多線程,那就從第三方以及自己看到的一些例子還有前段時(shí)間讀的多線程和內(nèi)存管理的書中分析理解總結(jié)一下多線程。

前言

多線程很多開發(fā)者多多少少相信也都有了解,以前有些東西理解的不是很透,慢慢的積累之后,這方面的東西也需要自己好好的總結(jié)一下。多線程從我剛接觸到iOS的時(shí)候就知道這玩意挺重要的,但那時(shí)也是能力有限,沒辦法很好的理解它,要是只是查它的概念性的東西,網(wǎng)上一搜一大把,我們?cè)倌菢尤タ偨Y(jié)就顯得意義不大了。這篇文章從我剛開始構(gòu)思著去寫的時(shí)候,就希望自己能換個(gè)角度去寫,想從實(shí)際問(wèn)題出發(fā)總結(jié)多線程,那就從第三方以及自己看到的一些例子還有前段時(shí)間讀的多線程和內(nèi)存管理的書中分析理解總結(jié)一下多線程。

[[225616]]

這幾個(gè)概念很容易繞暈

一 進(jìn)程:進(jìn)程就是線程的容器,你打開一個(gè)App就是打開了一個(gè)進(jìn)程,QQ有QQ的進(jìn)程,微信有微信的進(jìn)程,一個(gè)進(jìn)程可以包含多個(gè)線程,要是把進(jìn)程比喻成一條高速公路,線程就是高速路上的一條條車道,也正是因?yàn)橛辛诉@些車道,整個(gè)交通的運(yùn)行效率變得更高,也正是因?yàn)橛辛硕嗑€程的出現(xiàn),整個(gè)系統(tǒng)運(yùn)行效率變得更高。

二 線程:線程就是在進(jìn)程中我么開辟的一條條為我們做事的進(jìn)程實(shí)體,總結(jié)的通俗一點(diǎn),線程就是我們?cè)谶M(jìn)程上開辟的一條條做我們想做的事的通道。 一條線程在一個(gè)時(shí)間點(diǎn)上只能做一件“事”,多線程在同一時(shí)間點(diǎn)上,就能做多件“事”,這個(gè)理解,還是我們前面說(shuō)的高速路的例子。

一條高速路是一個(gè)進(jìn)程, 一條條車道就是不同的線程,在過(guò)收費(fèi)站的時(shí)候,這條進(jìn)程上要是只有一條線程,也就是一條高速路上只有一個(gè)車道,那你就只能排隊(duì)一輛一輛的通過(guò),同一時(shí)間不可能有兩輛車一起過(guò)去,但要是你一個(gè)進(jìn)程上有多個(gè)線程,也就是高速路上有幾個(gè)車道,也就有多個(gè)窗口收費(fèi),這樣的話同一時(shí)間就完全有可能兩輛車一起交完費(fèi)通過(guò)了,這樣說(shuō)相信也能理解這個(gè)進(jìn)程和線程的關(guān)系了。

  • 同步線程:同步線程會(huì)阻塞當(dāng)前的線程去執(zhí)行同步線程里面想做的“事”(任務(wù)),執(zhí)行完之后才會(huì)返回當(dāng)前線程。
  • 異步線程:異步線程不會(huì)阻塞當(dāng)前的線程去執(zhí)行異步線程里面想做的“事”,因?yàn)槭钱惒剑运鼤?huì)重新開啟一個(gè)線程去做想做的“事”。

三 隊(duì)列:隊(duì)列就是用來(lái)管理下面說(shuō)的“任務(wù)”的,它采用的是先進(jìn)先出(FIFO)的原則,它衍生出來(lái)的就是下面的它的分類并行和串行隊(duì)列,一條線程上可以有多個(gè)隊(duì)列。

  • 并行隊(duì)列:這個(gè)隊(duì)列里面的任務(wù)是可以并發(fā)(同時(shí))執(zhí)行的,由于我們知道,同步執(zhí)行任務(wù)不會(huì)開啟新的線程,所以并行隊(duì)列同步執(zhí)行任務(wù)任務(wù)只會(huì)在一條線程里面同步執(zhí)行這些任務(wù),又由于同步執(zhí)行也就是在當(dāng)前線程中做事,這個(gè)時(shí)候就需要一件一件的讓“事”(任務(wù))做完在接著做下一個(gè)。但要是是并發(fā)隊(duì)列異步執(zhí)行,就對(duì)應(yīng)著開啟異步線程執(zhí)行要做的“事”(任務(wù)),就會(huì)同一時(shí)間又許多的“事”被做著。
  • 串行隊(duì)列:這個(gè)隊(duì)列里面的任務(wù)是串行也就是一件一件做的,串行同步會(huì)一件一件的等事做完再接著做下一件,要是異步的就會(huì)開啟一條新的線程串行的執(zhí)行我們的任務(wù)。

四 任務(wù):任務(wù)按照自己通俗一點(diǎn)的理解,就是提到的“事”這個(gè)概念,這個(gè)“事”就可以理解為任務(wù),那這個(gè)“事”也肯定是在線程上面執(zhí)行的(不管是在當(dāng)前線程還是你另開啟的線程)。這個(gè)“事”你可以選擇同步或者而是異步執(zhí)行,這就衍生出了東西也就契合線程上面的同步線程和異步線程。

  • 同步任務(wù):不需要開啟新的線程,在當(dāng)前線程執(zhí)行就可以。
  • 異步任務(wù):你需要開辟一條新的線程去異步的執(zhí)行這個(gè)任務(wù)。

iOS當(dāng)中還有一個(gè)特殊的串行隊(duì)列-- 主隊(duì)列, 這個(gè)主隊(duì)列中運(yùn)行著一條特殊的線程 -- 主線程

主線程又叫UI線程,UI線程顧名思義主要的任務(wù)及時(shí)處理UI,也只有主線程有處理UI的能力,其他的耗時(shí)間的操作我們就放在子線程(也就是開辟線程)去執(zhí)行,開線程也會(huì)占據(jù)一定的內(nèi)存的,所以不要同時(shí)開啟很多的線程。

通過(guò)上面的內(nèi)容解釋了多線程里面幾個(gè)關(guān)鍵的概念的東西,要是有不理解的地方歡迎多交流,下面再給出隊(duì)列執(zhí)行時(shí)候的一個(gè)運(yùn)行的表格,我們一個(gè)一個(gè)慢慢的解釋。

 

NSThread

其實(shí)在我們?nèi)粘5拈_發(fā)中NSThread使用也是挺多的,具體關(guān)于它的一些我們需要注意的地方我們一步步的開始說(shuō),先看看它的初始化的幾個(gè)方法

 

  1. /* 
  2.  初始化NSThread的類方法,具體的任務(wù)在Block中執(zhí)行 
  3.  + (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0)); 
  4.     
  5.  利用selector方法初始化NSThread,target指selector方法從屬于的對(duì)象  selector方法也是指定的target對(duì)象的方法 
  6.  + (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument; 
  7.     
  8.  初始化NSThread的方法,這兩個(gè)方法和上面兩個(gè)方法的區(qū)別就是這兩個(gè)你能獲取到NSThread的對(duì)象 
  9.  具體的參數(shù)和前面解釋的參數(shù)意義都是一樣的 
  10.  切記一點(diǎn):  下面兩個(gè)方法初始化的NSThread你需要手動(dòng)start開啟線程 
  11.  - (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument NS_AVAILABLE(10_5, 2_0); 
  12.     
  13.  - (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0)); 
  14.  */ 

除了上面四個(gè)我們提出的方法,我們?cè)诔跏蓟@個(gè)問(wèn)題上還需要注意的還有一點(diǎn),就是 NSObject (NSThreadPerformAdditions) ,為我們的NSObject添加的這個(gè)類別,它里面的具體的一些方法我們也是很常用的:

 

  1. /* 
  2.  這個(gè)方法你執(zhí)行的aSelector就是在MainThread執(zhí)行的,也就是在主線程 
  3.  注意這里的waitUntilDone這個(gè)后面的BOOL類型的參數(shù),這個(gè)參數(shù)表示是否等待一直到aSelector這個(gè)方法執(zhí)行結(jié)束 
  4.  modes是RunLoop的運(yùn)行的類型這個(gè)RunLoop我也會(huì)好好在總結(jié)后面 
  5.  - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array; 
  6.     
  7.  - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait; 
  8.    // equivalent to the first method with kCFRunLoopCommonModes 
  9.     
  10.  上面的兩個(gè)方法是直接在主線程里面運(yùn)行,下面的這兩個(gè)方法是要在你初始化的thr中去運(yùn)行,其他的參數(shù)和上面解釋的一樣 
  11.  - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array NS_AVAILABLE(10_5, 2_0); 
  12.     
  13.  - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0); 
  14.    // equivalent to the first method with kCFRunLoopCommonModes 
  15.     
  16.  - (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg NS_AVAILABLE(10_5, 2_0); 
  17.  */ 

我們?cè)谡f(shuō)說(shuō)前面說(shuō)的waitUntilDone后面的這個(gè)BOOL類型的參數(shù),這個(gè)參數(shù)的意義有點(diǎn)像我們是否同步執(zhí)行aSelector這個(gè)任務(wù)!具體的看下面兩張圖的內(nèi)容就一目了然了:

 

在看看等于YES的時(shí)候結(jié)果的輸出情況:

 

關(guān)于NSThread我們?cè)僬f(shuō)下面幾個(gè)方法的具體的含義就不在描述了,關(guān)于NSThread有什么其他的問(wèn)題,可以加我QQ交流:

 

  1. /* 
  2.     
  3.  設(shè)置線程沉睡到指定日期 
  4.  + (void)sleepUntilDate:(NSDate *)date
  5.     
  6.  線程沉睡時(shí)間間隔,這個(gè)方法在設(shè)置啟動(dòng)頁(yè)間隔的時(shí)候比較常見 
  7.  + (void)sleepForTimeInterval:(NSTimeInterval)ti; 
  8.     
  9.  線程退出,當(dāng)執(zhí)行到某一個(gè)特殊情況下的時(shí)候你可以退出當(dāng)前的線程,注意不要在主線程隨便調(diào)用 
  10.  + (void)exit; 
  11.     
  12.  線程的優(yōu)先級(jí) 
  13.  + (double)threadPriority; 
  14.     
  15.  設(shè)置線程的優(yōu)先級(jí) 
  16.  + (BOOL)setThreadPriority:(double)p; 
  17.     
  18.  */ 

NSOperation

多線程我們還得提一下NSOperation,它可能比我們認(rèn)識(shí)中的要強(qiáng)大一點(diǎn),NSOperation也是有很多東西可以說(shuō)的,前面的NSThread其實(shí)也是一樣,這些要是仔細(xì)說(shuō)的話都能寫一篇文章出來(lái),可能以后隨著自己接觸的越來(lái)越多,關(guān)于多線程這一塊的東西我們會(huì)獨(dú)立的創(chuàng)建一個(gè)分類總結(jié)出去。

首先得知道NSOperation是基于GCD封裝的,NSOperation這個(gè)類本身我們使用的時(shí)候不躲,更多的是集中在蘋果幫我們封裝好的NSInvocationOperation和NSBlockOperation

你command一下NSOperation進(jìn)去看看,有幾個(gè)點(diǎn)你還是的了解一下的,主要的就是下面的幾個(gè)方法:

 

  1. NSOperation * operation = [[NSOperation alloc]init]; 
  2. [operation start];   //開始 
  3. [operation cancel]; //取消 
  4. [operation setCompletionBlock:^{ 
  5.     //operation完成之后的操作 
  6. }]; 

我們具體的說(shuō)一下我們上面說(shuō)的兩個(gè)類:NSInvocationOperation和NSBlockOperation,先看看NSInvocationOperation的初始化:

 

  1. /* 
  2.     
  3.  初始化方法 看過(guò)前面的文章之后它的target 、sel 、arg 等參數(shù)相信不難理解 
  4.  -(nullable instancetype)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg; 
  5.     
  6.  -(instancetype)initWithInvocation:(NSInvocation *)inv NS_DESIGNATED_INITIALIZER; 
  7.     
  8.  */ 

補(bǔ)充: NS_DESIGNATED_INITIALIZER 指定初識(shí)化方法并不是對(duì)使用者。而是對(duì)內(nèi)部的現(xiàn)實(shí),可以點(diǎn)擊進(jìn)去具體了解一下它!NSInvocationOperation其實(shí)是同步執(zhí)行的,因此單獨(dú)使用的話就價(jià)值不大了,它和NSOperationQueue一起去使用才能實(shí)現(xiàn)多線程調(diào)用。這個(gè)我們后面再具體的說(shuō)

在看看NSBlockOperation這個(gè),它重要的方法就我們下面的兩個(gè)

 

  1. /* 
  2.  初始化方法 
  3.  + (instancetype)blockOperationWithBlock:(void (^)(void))block; 
  4.     
  5.  添加一個(gè)可以執(zhí)行的block到前面初始化得到的NSBlockOperation中 
  6.  - (void)addExecutionBlock:(void (^)(void))block; 
  7.  */ 

NSBlockOperation這個(gè)我們得提一點(diǎn): 它的最大的并發(fā)具體的最大并發(fā)數(shù)和運(yùn)行環(huán)境也是有關(guān)系的,具體的內(nèi)容我們可以戳戳這里同行總結(jié)以及驗(yàn)證的,我們由于篇幅的原因就不在這里累贅。

其實(shí)只要是上面這些的話是不夠我們?nèi)粘J褂玫模€有一個(gè)激活他們倆的類我們也得說(shuō)說(shuō):NSOPerationQueue 下面是關(guān)于它的大概的一個(gè)說(shuō)明,都挺簡(jiǎn)單,就不在特意寫Demo。

 

關(guān)于NSOperation的我們就說(shuō)這么多,下面重點(diǎn)說(shuō)一下GCD。

主角GCD -- 主線程

1、我們先從主隊(duì)列,主線程開始說(shuō)起,通過(guò)下面的方法我們就可以獲取得到主隊(duì)列:

  1. dispatch_queue_t mainqueue = dispatch_get_main_queue(); 

2、我們?cè)谥骶€程同步執(zhí)行任務(wù),下面是操作的結(jié)果以及打印的信息:

 

我們解釋一下為什么在主線程中執(zhí)行同步任務(wù)會(huì)出現(xiàn)這個(gè)結(jié)果,我們一步一步的梳理一下這個(gè)執(zhí)行過(guò)程:

  1. 獲取到在主隊(duì)列主線程中執(zhí)行了最前面的打印信息,這個(gè)沒什么問(wèn)題
  2. 開始執(zhí)行dispatch_sync這個(gè)函數(shù),主隊(duì)列是串行隊(duì)列,這個(gè)函數(shù)會(huì)把這個(gè)任務(wù)插入到主隊(duì)列的最后面(理解隊(duì)列添加任務(wù))
  3. 主線程執(zhí)行到這里的時(shí)候就會(huì)等待插入的這個(gè)同步任務(wù)執(zhí)行完之后再執(zhí)行后面的操作
  4. 但由于這個(gè)同步任務(wù)是插入到主隊(duì)列的最后面,最隊(duì)列前面的任務(wù)沒有執(zhí)行完之前是不會(huì)執(zhí)行這個(gè)block的(主線程在執(zhí)行initMainQueue任務(wù))
  5. 這樣就造成了一個(gè)相互等待的過(guò)程,主線程在等待block完返回,block卻在等待主線程執(zhí)行它,這樣就造成了死鎖,看打印的信息你也就知道block是沒有被執(zhí)行的。

這里我們你可能會(huì)思考,主隊(duì)列是一個(gè)串行隊(duì)列,那我們?cè)谥骶€程中添加一個(gè)串行隊(duì)列,再給串行隊(duì)列添加一個(gè)同步任務(wù),這時(shí)候和前面主線程主隊(duì)列添加同步任務(wù)不就場(chǎng)景一樣了嗎?那結(jié)果呢? 我們看看下面的打印:

 

我們按照前面的方式解釋一下這個(gè)的執(zhí)行步驟:

  • 主線程在執(zhí)行主隊(duì)列中的方法initSerialQueue,到這個(gè)方法時(shí)候創(chuàng)建了一個(gè)串行隊(duì)列(注意不是主隊(duì)列)打印了前面的第一條信息
  • 執(zhí)行到dispatch_sync函數(shù),這個(gè)函數(shù)給這個(gè)串行隊(duì)列中添加了一個(gè)同步任務(wù),同步任務(wù)是會(huì)立馬執(zhí)行的
  • 主線程就直接操作執(zhí)行了這個(gè)隊(duì)列中的同步任務(wù),打印的第二條信息
  • 主線程接著執(zhí)行下面的第三條打印信息

理解:看這個(gè)執(zhí)行的過(guò)程對(duì)比前面的,你就知道了不同的地方就是前面是添加在了主隊(duì)列當(dāng)中,但這里有添加到主隊(duì)列,由于是插入到主隊(duì)列的末尾,所以需要主隊(duì)列的任務(wù)都執(zhí)行完才能指定到它,但主線程執(zhí)行到initMainQueue這個(gè)方法的時(shí)候在等待這個(gè)方法中添加的同步任務(wù)執(zhí)行完接著往下執(zhí)行,但它里面的同步任務(wù)又在等待主線程執(zhí)行完在執(zhí)行它,就相互等待了,但主線程執(zhí)行不是主隊(duì)列里面的同步任務(wù)的時(shí)候是不需要主線程執(zhí)行完所有操作在執(zhí)行這個(gè)任務(wù)的,這個(gè)任務(wù)是它添加到串行隊(duì)列的開始也是結(jié)束的任務(wù),由于不需要等待,就不會(huì)造成死鎖!

上面這個(gè)問(wèn)題經(jīng)常會(huì)看到有人問(wèn),有許多解釋,也希望自己能把這個(gè)問(wèn)題給說(shuō)清楚了!

3、主線程這里我們?cè)偬嵋稽c(diǎn),就是線程間的信息簡(jiǎn)單傳遞

前面我們有說(shuō)到主線程又叫做UI線程,所有關(guān)于UI的事我們都是在主線程里面更新的,像下載數(shù)據(jù)以及數(shù)據(jù)庫(kù)的訪問(wèn)等這些耗時(shí)的操作我們是建議放在子線程里面去做,那就會(huì)產(chǎn)生子線程處理完這些之后要回到主線程更行UI的問(wèn)題上,這一點(diǎn)值得我們好好的注意一下,但其實(shí)這一點(diǎn)也是我們用的最多的,相信大家也都理解!

主角GCD -- 串行隊(duì)列

串行隊(duì)列的概念性的東西我們就不在這里累贅,不管是串行隊(duì)列+同步任務(wù)還是串行隊(duì)列+異步任務(wù)都簡(jiǎn)單,有興趣可以自己是這寫一下,后面分析會(huì)提到他們的具體使用的,我們?cè)谝粋€(gè)稍微比前面的說(shuō)的復(fù)雜一點(diǎn)點(diǎn)的問(wèn)題,串行隊(duì)列+異步+同步,可以先試著不要往下面看先分析一下下面這段代碼的執(zhí)行結(jié)果是什么?

 

  1. static void * DISPATCH_QUEUE_SERIAL_IDENTIFY; 
  2.    
  3. -(void)initDiapatchQueue{ 
  4.    
  5.         dispatch_queue_t serialQueue = dispatch_queue_create(DISPATCH_QUEUE_SERIAL_IDENTIFY, DISPATCH_QUEUE_SERIAL); 
  6.         dispatch_async(serialQueue, ^{ 
  7.               
  8.                 NSLog(@"一個(gè)異步任務(wù)的內(nèi)容%@",[NSThread currentThread]); 
  9.                 dispatch_sync(serialQueue, ^{ 
  10.                       
  11.                         NSLog(@"一個(gè)同步任務(wù)的內(nèi)容%@",[NSThread currentThread]); 
  12.                 }); 
  13.         }); 

不知道你分析數(shù)來(lái)的這點(diǎn)代碼的結(jié)果是什么,我們這里來(lái)看看結(jié)果,然后和上面一步一步的分析一下它的整個(gè)的執(zhí)行過(guò)程,就能找到答案:

 

答案就是crash了,其實(shí)也是死鎖,下面一步一步的走一下這整個(gè)過(guò)程,分析一下哪里死鎖了:

  1. 主線程主隊(duì)列中執(zhí)行任務(wù)initDispatchQueue,進(jìn)入了這個(gè)方法,在這個(gè)方法里面創(chuàng)建了一個(gè)串行隊(duì)列,這一步相信大家都明白,沒什么問(wèn)題。
  2. 給這個(gè)串行隊(duì)列添加了一個(gè)異步任務(wù),由于是異步任務(wù),所以會(huì)開啟一條新的線程,為了方便描述,我們把新開的這個(gè)線程記做線程A, 把這個(gè)任務(wù)記做任務(wù)A,也由于是異步任務(wù),主線程就不會(huì)等待這個(gè)任務(wù)返回,就接著往下執(zhí)行其他任務(wù)了。
  3. 接下來(lái)的分析就到了這個(gè)線程A上,這個(gè)任務(wù)A被添加到串行隊(duì)列之后就開始在線程A上執(zhí)行,打印出了我們的第一條信息,也證明了不是在主線程,這個(gè)也沒問(wèn)題。
  4. 線程A開始執(zhí)行這個(gè)任務(wù)A,進(jìn)入這個(gè)任務(wù)A之后在這個(gè)任務(wù)A里面又同步在串行隊(duì)列里面添加任務(wù),記做任務(wù)B,由于任務(wù)B是dispatch_sync函數(shù)同步添加的,需要立馬被執(zhí)行,就等待線程A執(zhí)行它
  5. 但是這個(gè)任務(wù)B是添加到串行隊(duì)列的末尾的,線程A在沒有執(zhí)行完當(dāng)前任務(wù)A是不會(huì)去執(zhí)行它的,這樣就造成線程A在等待當(dāng)前任務(wù)A執(zhí)行完,任務(wù)B又在等待線程A執(zhí)行它,就形成了死鎖

經(jīng)過(guò)上面的分析,你就能看到這個(gè)場(chǎng)景和你在主線程同步添加任務(wù)是一樣的,我們?cè)僮屑?xì)的考慮一下這整個(gè)過(guò)程,在分析一下上面主線程+串行隊(duì)列+同步任務(wù)為什么沒有形成死鎖!相互對(duì)比理解,就能把整個(gè)問(wèn)題想明白。

主角GCD -- 并行隊(duì)列

下面我們接著再說(shuō)說(shuō)這個(gè)并行隊(duì)列,并行隊(duì)列+同步執(zhí)行或者并行隊(duì)列+異步執(zhí)行這個(gè)我們也就沒什么好說(shuō)的了,在這里說(shuō)說(shuō)并行+異步的需要注意的地方,不知道大家有沒有想過(guò),并行的話很多任務(wù)會(huì)一起執(zhí)行,要是異步任務(wù)的話會(huì)開啟新的線程,那是不是我們添加了十個(gè)異步任務(wù)就會(huì)開啟十條線程呢?那一百個(gè)異步任務(wù)豈不是要開啟一百條線程,答案肯定是否定的!那系統(tǒng)到底是怎么處理的,我們也說(shuō)說(shuō),下面的是高級(jí)編程書里面的解釋我們梳理一下給出結(jié)論。

  • 當(dāng)為DISPATCH_QUEUE_CONCURRENT的時(shí)候,不用等待前面任務(wù)的處理結(jié)束,后面的任務(wù)也是能夠直接執(zhí)行的
  • 并行執(zhí)行的處理數(shù)量取決于當(dāng)前系統(tǒng)的狀態(tài),即iOS和OS X基于Dispatch Queue中的處理數(shù)、CPU核數(shù)以及CPU負(fù)荷等當(dāng)前系統(tǒng)狀態(tài)來(lái)決定DISPATCH_QUEUE_CONCURRENT中并行執(zhí)行的處理數(shù)
  • iOS 和 OS X的核心 -- XNU內(nèi)核決定應(yīng)當(dāng)使用的線程數(shù),并且生成所需的線程執(zhí)行處理
  • 當(dāng)處理結(jié)束,應(yīng)當(dāng)執(zhí)行的處理數(shù)減少時(shí),XNU內(nèi)核會(huì)結(jié)束不在需要的線程

處理并行異步任務(wù)時(shí)候線程是可以循環(huán)往復(fù)使用的,比如任務(wù)1的線程執(zhí)行完了任務(wù)1,線程可以接著去執(zhí)行后面沒有執(zhí)行的任務(wù)

這里的東西就這些,我們?cè)谇懊娲嘘?duì)列的時(shí)候,串行隊(duì)列+異步任務(wù)嵌套同步任務(wù)會(huì)造成死鎖,那我們要是把它變成同步隊(duì)列呢?結(jié)果又會(huì)是什么樣子呢?我們看看下面這段代碼的執(zhí)行結(jié)果:

 

從上面的結(jié)果可以看得出來(lái),是沒有問(wèn)題的,這里我們就不在一步一步的分析它的執(zhí)行過(guò)程了,就說(shuō)說(shuō)為什么并行的隊(duì)列就沒有問(wèn)題,但是串行的隊(duì)列就會(huì)出問(wèn)題:

并行隊(duì)列添加了異步任務(wù)也是創(chuàng)建了一個(gè)新的線程,然后再在這個(gè)任務(wù)里面給并行隊(duì)列添加一個(gè)同步任務(wù),由于是并行隊(duì)列 ,執(zhí)行這個(gè)同步任務(wù)是不需要前面的異步任務(wù)執(zhí)行完了,就直接開始執(zhí)行,所以也就有了下面的打印信息,通過(guò)上面幾個(gè)問(wèn)題,相信理解了之后,對(duì)于串行隊(duì)列或者并行隊(duì)列添加同步任務(wù)或者異步任務(wù)都有了一個(gè)比較深的理解了,我們?cè)俳又驴偨Y(jié)。

GCD不僅僅這些

關(guān)于GCD的內(nèi)容還有下面這些都是值得我們關(guān)注的,下面我們開始一一說(shuō)一說(shuō):

1、dispatch_barrier_async

dispatch_barrier_async 函數(shù)是我們俗稱的柵欄方法,“柵欄”的意思理解一下字面的,就是把外面和里面阻隔開,這個(gè)函數(shù)的作用就是這樣,把插入的這個(gè)柵欄之前和之后的阻隔開,等前面的執(zhí)行完了就執(zhí)行“柵欄函數(shù)”插入的任務(wù),等柵欄的任務(wù)執(zhí)行結(jié)束了就開始執(zhí)行柵欄后面的任務(wù)。看下面一個(gè)簡(jiǎn)單的Demo就理解了。

 

從上面就可以看到,我們把0插入到第三個(gè)任務(wù)的位置,它是等前面的兩個(gè)任務(wù)執(zhí)行完了,在去執(zhí)行第三個(gè),要是你覺得這里前兩個(gè)任務(wù)簡(jiǎn)單,執(zhí)行不需要太多的時(shí)間的話,你可以試著把前面兩個(gè)任務(wù)的“任務(wù)量”設(shè)置大一點(diǎn),這樣有助于你更好的理解這個(gè)“柵欄”操作!

2、dispatch_after

dispatch_after 延時(shí)操作

如果某一條任務(wù)你想等多少時(shí)間之后再執(zhí)行的話,你就完全可以使用這個(gè)函數(shù)處理,寫法很簡(jiǎn)單,因?yàn)橐呀?jīng)幫我們封裝好了,看下面這兩行代碼:

 

  1. // DISPATCH_TIME_NOW 當(dāng)前時(shí)間開始 
  2. // NSEC_PER_SEC 表示時(shí)間的宏,這個(gè)可以自己上網(wǎng)搜索理解 
  3. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
  4.           
  5.         NSLog(@"延遲了10秒執(zhí)行"); 
  6. }); 

3、dispatch_apply

dispatch_apply 類似一個(gè)for循環(huán),會(huì)在指定的dispatch queue中運(yùn)行block任務(wù)n次,如果隊(duì)列是并發(fā)隊(duì)列,則會(huì)并發(fā)執(zhí)行block任務(wù),dispatch_apply是一個(gè)同步調(diào)用,block任務(wù)執(zhí)行n次后才返回。 由于它是同步的,要是我們下面這樣寫就會(huì)有出問(wèn)題:

 

可以看到出問(wèn)題了,但我們要是把它放在串行隊(duì)列或者并行隊(duì)列就會(huì)是下面這樣的情況

 

4、dispatch_group_t

dispatch_group_t的作用我們先說(shuō)說(shuō),在追加到Dispatch Queue 中的多個(gè)任務(wù)全部結(jié)束之后想要執(zhí)行結(jié)束的處理,這種情況也會(huì)經(jīng)常的出現(xiàn),在只使用一個(gè)Serial Dispatch Queue時(shí),只要將想執(zhí)行的操作全部追加該Serial Dispatch Queue中并且追加在結(jié)束處理就可以實(shí)現(xiàn),但是在使用 Concurrent Dispatch Queue 時(shí)或者同時(shí)使用多個(gè) Dispatch Queue時(shí)候,就比較的復(fù)雜了,在這樣的情況下 Dispatch Group 就可以發(fā)揮它的作用了。看看下面的這段代碼:

 

  1. -(void)testDispatch_group_t{ 
  2.    
  3.         dispatch_group_t group_t = dispatch_group_create(); 
  4.         dispatch_queue_t queue_t = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
  5.         dispatch_group_async(group_t, queue_t, ^{ 
  6.                    
  7.                 NSLog(@"1--當(dāng)前的線程%@",[NSThread currentThread]); 
  8.         }); 
  9.         dispatch_group_async(group_t, queue_t, ^{ 
  10.                    
  11.                 NSLog(@"2--當(dāng)前的線程%@",[NSThread currentThread]); 
  12.         }); 
  13.         dispatch_group_async(group_t, queue_t, ^{ 
  14.                    
  15.                 NSLog(@"3--當(dāng)前的線程%@",[NSThread currentThread]); 
  16.         }); 
  17.         dispatch_group_async(group_t, queue_t, ^{ 
  18.                    
  19.                 for (int i = 1; i<10; i++) { 
  20.                         6  
  21.                      NSLog(@"4--當(dāng)前的線程%@",[NSThread currentThread]); 
  22.                 } 
  23.         }); 
  24.         // 當(dāng)前的所有的任務(wù)都執(zhí)行結(jié)束 
  25.         dispatch_group_notify(group_t, queue_t, ^{ 
  26.               
  27.                 NSLog(@"前面的全都執(zhí)行結(jié)束了%@",[NSThread currentThread]); 
  28.         }); 

這段代碼的意圖很明顯,看了下面的打印信息這個(gè)你也就理解它了:

 

總結(jié): 關(guān)于多線程的最基本的問(wèn)題暫時(shí)先總結(jié)這么多,還有許多的問(wèn)題,自己也在總結(jié)當(dāng)中,比如以下線程鎖等等的問(wèn)題,等總結(jié)到差不多的時(shí)候再分享!

責(zé)任編輯:未麗燕 來(lái)源: CocoaChina
相關(guān)推薦

2009-03-12 10:11:00

綜合布線規(guī)劃網(wǎng)絡(luò)布局

2022-04-07 18:49:56

項(xiàng)目場(chǎng)景數(shù)據(jù)庫(kù)

2009-04-17 22:25:16

多核四核CPU

2024-06-12 08:04:33

2018-01-12 10:25:48

Nginx信號(hào)集master

2009-01-08 09:52:00

2010-08-24 09:11:05

無(wú)線網(wǎng)絡(luò)故障

2025-07-31 00:00:15

2014-07-21 10:03:56

2010-03-03 17:44:07

Python多線程

2009-10-14 11:38:14

數(shù)據(jù)中心網(wǎng)絡(luò)布局

2023-11-30 15:38:54

2021-07-19 15:12:21

Python編程語(yǔ)言

2013-07-16 10:12:14

iOS多線程多線程概念多線程入門

2011-08-02 10:26:59

iOS 多線程 線程

2015-07-22 09:51:51

iOS開發(fā)線程

2015-07-22 09:39:38

IOS多線程同步

2016-04-12 09:48:24

nsthread多線程ios

2013-07-16 12:13:27

iOS多線程多線程概念GCD

2013-07-16 10:57:34

iOS多線程多線程概念多線程入門
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

天天影视欧美综合在线观看| 日本激情视频在线观看| 在线成人欧美| 亚洲欧美国产一区二区三区| 天天综合网久久| av大大超碰在线| 久久综合精品国产一区二区三区 | 国产中文一区二区| 亚洲欧美一二三区| 欧美国产免费| 国产亚洲综合久久| 无码人妻精品一区二区三区99不卡| 亚洲日本天堂| 一区二区三区中文在线观看| 欧日韩一区二区三区| 国产视频手机在线观看| 噜噜噜91成人网| 欧美日本在线视频中文字字幕| 添女人荫蒂视频| 中文字幕成人| 欧美在线色视频| 欧美国产视频一区| 日本激情在线观看| 国产亚洲福利社区一区| 成人一区二区三区四区| 中文字幕永久在线视频| 亚洲美女啪啪| 欧美日韩成人网| 成年人免费视频播放| 亚洲国产欧美日韩在线观看第一区 | 亚洲欧美精品一区| 国产乱淫av麻豆国产免费| 不卡一二三区| 福利微拍一区二区| 国产黄色激情视频| 蜜芽在线免费观看| 国产欧美一二三区| 欧美日韩一区二区三区免费| 国产小视频一区| 国产精品主播直播| 成人写真视频福利网| 国产一级片一区二区| 亚洲人体大胆视频| 久久久久久综合网天天| 欧美日韩一级大片| 亚洲欧美日韩高清在线| 日韩一区二区欧美| 99自拍偷拍视频| 欧美一区二区性| 国产一区二区三区18| 熟女俱乐部一区二区| 色吊丝一区二区| 日韩h在线观看| 强迫凌虐淫辱の牝奴在线观看| 国产毛片久久久| 欧美精品一区二区三区高清aⅴ | 久久久久久久久一| 青娱乐国产91| 电影av在线| 国产精品午夜免费| 一区二区三区免费看| 在线观看a视频| 综合婷婷亚洲小说| www.男人天堂网| 成人性生交大片免费看在线播放| 亚洲一区在线观看免费观看电影高清| 99亚洲国产精品| 牛牛电影国产一区二区| 亚洲国产日韩a在线播放| 欧美成人高潮一二区在线看| 在线观看v片| 日本韩国精品在线| jizz欧美性11| 蜜桃在线一区| 日韩不卡在线观看| 无码人妻aⅴ一区二区三区69岛| heyzo久久| 久久天天躁狠狠躁老女人| 黄色一级免费视频| 亚洲欧美日韩国产综合精品二区| 国产精品久久久999| 在线中文字幕网站| 国产精品自拍在线| 国偷自产av一区二区三区小尤奈| 欧美日韩国产亚洲沙发| 国产精品乱人伦一区二区| wwwjizzjizzcom| 忘忧草在线日韩www影院| 欧美三级日韩在线| 日本r级电影在线观看| 日韩最新在线| 久久伊人色综合| 国产高清中文字幕| 精品一区二区在线视频| 精品欧美日韩在线| 99se视频在线观看| 亚洲国产精品久久人人爱蜜臀 | 成人日韩精品| 日韩欧美国产系列| 亚洲区免费视频| 中文字幕一区二区av| 欧美一区亚洲一区| 国产后入清纯学生妹| 久久精品一区四区| 青青视频免费在线观看| 经典三级一区二区| 精品久久久久久综合日本欧美| 精品无码国产污污污免费网站 | 亚洲精品乱码久久久久久自慰| 日韩电影精品| 亚洲男人7777| 国产在线免费视频| 久久激五月天综合精品| 欧美裸体网站| 98色花堂精品视频在线观看| 欧美日韩国产综合视频在线观看 | 亚洲国产高清aⅴ视频| 加勒比成人在线| 电影91久久久| 中文日韩在线观看| 国产一级做a爱片久久毛片a| 国产福利一区在线| 久久久一二三四| 秋霞国产精品| 国产视频久久久久久久| 精品97人妻无码中文永久在线| 日韩av网站在线观看| 精品视频免费观看| 激情网站在线| 日韩欧美国产麻豆| 五月天免费网站| 日韩黄色一级片| 久久久影院一区二区三区| av毛片在线播放| 欧美肥妇毛茸茸| eeuss中文字幕| 日韩二区在线观看| 欧美亚洲另类在线一区二区三区| 成年人在线网站| 亚洲国产精品yw在线观看 | 狠狠干综合网| 99伊人久久| 日本h片在线观看| 欧美一级午夜免费电影| 国产三级国产精品国产国在线观看| 免费av成人在线| 亚洲欧洲日韩综合二区| 久久69成人| 日韩中文在线中文网三级| 一本大道伊人av久久综合| 国产精品成人网| 日韩在线不卡一区| 欧美在线资源| 国产伦精品一区二区三区四区免费| 成人免费一区二区三区牛牛| 精品福利一二区| 麻豆久久久久久久久久| av一区二区不卡| 超碰97人人射妻| 国产一区二区三区四区| 国产精品福利久久久| 午夜激情在线观看| 日韩一区二区中文字幕| 玖玖爱免费视频| 91一区在线观看| 不卡av免费在线| 99国产精品免费视频观看| 91色琪琪电影亚洲精品久久| 欧美色图天堂| 日韩久久精品电影| 日韩久久久久久久久久| ●精品国产综合乱码久久久久| 又黄又爽又色的视频| 伊人影院久久| 欧美专区一二三| 麻豆一区在线| 午夜伦理精品一区| 福利在线视频导航| 91精品国产综合久久精品| 九九九国产视频| 国产性做久久久久久| 欧美激情第一区| 亚洲黄色成人| 性欧美.com| 国内视频在线精品| 国产精国产精品| 色黄网站在线观看| 亚洲欧美国产精品专区久久 | 精品一区二区三区视频在线观看 | 精品免费国产一区二区三区四区| 日本中文字幕在线免费观看| 国产精品麻豆99久久久久久| 美女黄色一级视频| 男女激情视频一区| 久久99中文字幕| 日韩免费一区| 精品久久久久久乱码天堂| 日韩国产91| 欧美亚洲另类视频| av在线免费网址| 亚洲性生活视频在线观看| 国产高清在线免费| 欧美亚洲高清一区二区三区不卡| 国产性生活网站| 中文字幕不卡在线观看| 中文字幕在线永久| 国产综合成人久久大片91| 无码人妻丰满熟妇区毛片| 欧美日韩国产色综合一二三四| 亚洲va久久久噜噜噜久久狠狠| 精品久久对白| 7777精品久久久大香线蕉小说| 91精品xxx在线观看| 国内精品在线一区| a视频在线播放| 色青青草原桃花久久综合 | 久久久久久日产精品| 亚洲国产精品狼友在线观看| 美女免费视频一区二区| 欧美三级一级片| 亚洲黄网站黄| 亚洲激情免费视频| 成人同人动漫免费观看| 欧美性天天影院| 日韩精品免费一区二区三区竹菊 | 亚洲国产欧美在线| 国内偷拍精品视频| 国产精品成人在线观看| 夫妇露脸对白88av| 久久精品亚洲国产奇米99| 午夜影院福利社| 国产a区久久久| 蜜桃视频无码区在线观看| 韩国av一区二区三区在线观看| 亚洲一级免费观看| 热久久国产精品| 一区二区三区 欧美| 久久午夜av| 欧美视频第三页| 丝瓜av网站精品一区二区| 91国视频在线| 国产亚洲在线观看| 国产视频一视频二| 国产欧美日韩综合一区在线播放| aa视频在线播放| 一级成人国产| 中文字幕乱码人妻综合二区三区| 六月丁香综合| 五月婷婷狠狠操| 久久国产夜色精品鲁鲁99| 午夜精品中文字幕| 精品一区中文字幕| 夜夜爽久久精品91| 国产99久久久国产精品免费看| 亚洲国产日韩在线一区| 国产91色综合久久免费分享| 天堂www中文在线资源| 北条麻妃一区二区三区| 波多野结衣加勒比| 91啪九色porn原创视频在线观看| 亚欧洲乱码视频| 日本一区二区三区dvd视频在线 | 91亚洲一线产区二线产区| 粉嫩绯色av一区二区在线观看| 亚洲美女精品视频| av一本久道久久综合久久鬼色| 毛片网站免费观看| 国产精品久久久久久久久免费樱桃 | 久久久亚洲国产| 中文日产幕无线码一区二区| 国产精品久久久久久久久久东京 | 蜜臀国产一区| 国产美女91呻吟求| 秋霞午夜一区二区三区视频| 国产精品久久精品国产| 外国成人在线视频| 午夜一区二区三区| 欧美国产激情| 欧美激情国产精品日韩| 狠狠色丁香婷婷综合| 久草视频福利在线| 国产亚洲精品超碰| 青娱乐91视频| 一本大道综合伊人精品热热| 91精东传媒理伦片在线观看| 亚洲精品一区二区三区99| 韩日在线视频| 欧美美女18p| 正在播放日韩精品| 亚洲999一在线观看www| 偷窥自拍亚洲色图精选| 中文字幕中文字幕在线中心一区| 影音国产精品| 777视频在线| av成人老司机| 国产精品丝袜一区二区| 五月激情综合色| 国产原创中文av| 亚洲精品视频中文字幕| www.久久久久.com| 国产成人精品久久二区二区91| 久久av网站| 日韩电影大全在线观看| 在线成人国产| 在线a免费观看| 国产欧美日韩卡一| 日韩三级小视频| 91精品一区二区三区久久久久久 | 精品国产一区二区三区成人影院 | 日韩成人av影视| 中文字幕一区二区人妻电影丶| 国产精品网站一区| 永久免费无码av网站在线观看| 日韩视频一区二区三区在线播放| 国产午夜视频在线观看| 久久久久久久一区二区| 精品视频国内| 亚洲自拍偷拍二区| 日日夜夜免费精品| 风间由美一二三区av片| 亚洲资源在线观看| 91欧美日韩麻豆精品| 亚洲无线码在线一区观看| 在线黄色的网站| 国产欧美日韩在线播放| 欧美日韩国产在线一区| 黄色大片网站在线观看| 色欧美日韩亚洲| 日本黄色免费视频| 欧美人成在线视频| 国产一区二区三区| 亚洲精品国产一区| 日韩成人免费电影| av黄色在线免费观看| 日韩欧美精品网址| 亚洲aⅴ乱码精品成人区| 欧美激情一区二区三区高清视频| 91视频亚洲| 综合久久国产| 国产美女娇喘av呻吟久久| 蜜桃av免费观看| 欧美视频日韩视频| av影片在线看| 国产日韩欧美中文| 欧美aaaa视频| 一区二区三区四区毛片| 中文字幕一区二区三区不卡| 亚洲图片视频小说| 色妞久久福利网| 国产精品视频首页| 无码人妻精品一区二区三区99v| 精品一区二区三区免费| 婷婷激情四射网| 日韩亚洲电影在线| 欧美性爽视频| 国内精品久久国产| 老司机精品福利视频| 91精品国自产在线| 欧美美女直播网站| www在线视频| 国产精品久久久对白| 国产深夜精品| 色噜噜日韩精品欧美一区二区| 色94色欧美sute亚洲13| av男人的天堂在线| 91精品国产99久久久久久红楼| 亚洲手机视频| 极品粉嫩小仙女高潮喷水久久| 色八戒一区二区三区| 日本精品在线| 国产亚洲欧美一区二区| 香蕉精品999视频一区二区| 无码少妇一区二区| 制服丝袜国产精品| xxxx成人| 亚洲欧洲国产精品久久| 国产成a人亚洲| 国产91国语对白在线| 日韩中文av在线| 狠狠一区二区三区| 久草综合在线观看| 亚洲欧美国产高清| 日韩在线无毛| 成人久久久久久久| 最新成人av网站| 影音先锋男人看片资源| 精品久久久久久久久久久院品网| 自拍偷拍欧美视频| 日本一二三区视频在线| 91污在线观看| 国产免费黄色网址| 国产91精品久久久久| 国产精品麻豆久久| 亚洲欧美日本一区| 91麻豆精品国产91久久久资源速度| 91在线三级| 伊人久久青草| 久久久青草青青国产亚洲免观| 国产精品无码久久久久成人app| 91av在线免费观看视频|