久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

并發(fā)編程之Operation Queue和GCD

 最初九月雪 2016-03-15

轉(zhuǎn)自Xcode Dev

并發(fā)編程之Operation Queue

隨著移動設(shè)備的更新?lián)Q代,,移動設(shè)備的性能也不斷提高,,現(xiàn)在流行的CPU已經(jīng)進入雙核、甚至四核時代,。如何充分發(fā)揮這些CPU的性能,,會變得越來越重要。在iOS中如果想要充分利用多核心CPU的優(yōu)勢,,就要采用并發(fā)編程,,提高CPU的利用率。iOS中并發(fā)編程中主要有2種方式Operation Queue和GCD(Grand Central Dispatch),。下面就來先來說一下Operation Queue,。

 

異步調(diào)用和并發(fā)

在深入之前,,首先說說異步調(diào)用和并發(fā),。這兩個概念在并發(fā)編程中很容易弄混淆。異步調(diào)用是指調(diào)用時無需等待結(jié)果返回的調(diào)用,,異步調(diào)用往往會觸發(fā)后臺線程處理,,比如NSURLConnection的異步網(wǎng)絡(luò)回調(diào)。并發(fā)是指多個任務(wù)(線程)同時執(zhí)行,。在異步調(diào)用的實現(xiàn)中往往采用并發(fā)機制,,然而并不是所有異步都是并發(fā)機制,也有可能是其他機制,,比如一些依靠中斷進行的操作,。

 

為什么Operation Queue

Operation Queue提供一個面向?qū)ο蟮牟l(fā)編程接口,支持并發(fā)數(shù),,線程優(yōu)先級,,任務(wù)優(yōu)先級,,任務(wù)依賴關(guān)系等多種配置,可以方便滿足各種復雜的多任務(wù)處理場景,。

1.面向?qū)ο蠼涌?/p>

2.支持并發(fā)數(shù)配置

3.任務(wù)優(yōu)先級調(diào)度

4.任務(wù)依賴關(guān)系

5.線程優(yōu)先級配置

 

NSOperation簡介

iOS并發(fā)編程中,,把每個并發(fā)任務(wù)定義為一個Operation,對應(yīng)的類名是NSOperation,。NSOperation是一個抽象類,,無法直接使用,它只定義了Operation的一些基本方法,。我們需要創(chuàng)建一個繼承于它的子類或者使用系統(tǒng)預(yù)定義的子類,。目前系統(tǒng)預(yù)定義了兩個子類:NSInvocationOperation和NSBlockOperation。

 

NSInvocationOperation

NSInvoationOperation是一個基于對象和selector的Operation,,使用這個你只需要指定對象以及任務(wù)的selector,,如果必要,你還可以設(shè)定傳遞的對象參數(shù),。

  1. NSInvocationOperation *invacationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomethingWithObj:) object:obj]; 

 

同時當這個Operation完成后,,你還可以獲取Operation中Invation執(zhí)行后返回的結(jié)果對象。

  1. id result = [invacationOperation result]; 

 

NSBlockOperation

在一個Block中執(zhí)行一個任務(wù),,這時我們就需要用到NSBlockOperation,。可以通過blockOperationWithBlock:方法來方便地創(chuàng)建一個NSBlockOperation:

  1. NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ 
  2.     //Do something here. 
  3. }]; 

運行一個Operation

調(diào)用Operation的start方法就可以直接運行一個Operation,。

  1. [operation start]; 

 

start方法用來啟動一個Operation任務(wù),。同時,Operation提供一個main方法,,你的所有任務(wù)都應(yīng)該在main中進行處理,。默認的start方法中會先做出一些異常判斷然后直接調(diào)用main方法。如果需要自定義一個NSOperation必須重載main方法來執(zhí)行你所想要執(zhí)行的任務(wù),。

  1. @implementation CustomOperation 
  2.  
  3. -(void)main { 
  4.    @try { 
  5.       // Do some work. 
  6.    } 
  7.    @catch(...) { 
  8.       // Exception handle. 
  9.    } 
  10. @end 

 

取消一個Operation

要取消一個Operation,,要向Operation對象發(fā)送cancel消息:

  1. [operation cancel]; 

當向一個Operation對象發(fā)送cancel消息后,并不保證這個Operation對象一定能立刻取消,,這取決于你的main中對cancel的處理,。如果你在main方法中沒有對cancel進行任何處理的話,發(fā)送cancel消息是沒有任何效果的,。為了讓Operation響應(yīng)cancel消息,,那么你就要在main方法中一些適當?shù)牡胤绞謩拥呐袛鄆sCancelled屬性,如果返回YES的話,,應(yīng)釋放相關(guān)資源并立刻停止繼續(xù)執(zhí)行,。

 

創(chuàng)建可并發(fā)的Operation

由于默認情況下Operation的start方法中直接調(diào)用了main方法,而main方法中會有比較耗時的處理任務(wù)。如果我們在一段代碼連續(xù)start了多個Operation,,這些Operation都是阻塞地依次執(zhí)行完,,因為第二個Operation必須等到第一個Operation執(zhí)行完start內(nèi)的main并返回。Operation默認都是不可并發(fā)的(使用了Operation Queue情況下除外,,Operation Queue會獨自管理自己的線程),,因為默認情況下Operation并不額外創(chuàng)建線程。我們可以通過Operation的isConcurrent方法來判斷Operation是否是可并發(fā)的,。如果要讓Operation可并發(fā),,我們需要讓main在獨立的線程中執(zhí)行,并將isConcurrent返回YES,。

  1. @implementation MyOperation{ 
  2.     BOOL        executing; 
  3.     BOOL        finished; 
  4.  
  5.  
  6. - (BOOL)isConcurrent { 
  7.     return YES; 
  8.  
  9. - (void)start { 
  10.    if ([self isCancelled]) 
  11.    { 
  12.       [self willChangeValueForKey:@"isFinished"]; 
  13.       finished = YES; 
  14.       [self didChangeValueForKey:@"isFinished"]; 
  15.       return; 
  16.    } 
  17.  
  18.    [self willChangeValueForKey:@"isExecuting"]; 
  19.    [NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil]; 
  20.    executing = YES; 
  21.    [self didChangeValueForKey:@"isExecuting"]; 
  22.  
  23. - (void)main { 
  24.    @try { 
  25.         // Do some work. 
  26.  
  27.         [self willChangeValueForKey:@"isFinished"]; 
  28.         [self willChangeValueForKey:@"isExecuting"]; 
  29.         executing = NO; 
  30.         finished = YES; 
  31.         [self didChangeValueForKey:@"isExecuting"]; 
  32.         [self didChangeValueForKey:@"isFinished"]; 
  33.  
  34.    } 
  35.    @catch(...) { 
  36.       // Exception handle. 
  37.    } 
  38.  
  39. @end 

 當你自定義了start或main方法時,,一定要手動的調(diào)用一些KVO通知方法,以便讓對象的KVO機制可以正常運作,。

 

設(shè)置Operation的completionBlock

每個Operation都可以設(shè)置一個completionBlock,,在Operation執(zhí)行完成時自動執(zhí)行這個Block。我們可以在此進行一些完成的處理,。completionBlock實現(xiàn)原理是對Operation的isFinnshed字段進行KVO(Key-Value Observing),,當監(jiān)聽到isFinnished變成YES時,就執(zhí)行completionBlock,。

  1. operation.completionBlock = ^{ 
  2.     NSLog(@"finished"); 
  3. }; 

 

設(shè)置Operation的線程優(yōu)先級

我們可以為Operation設(shè)置一個線程優(yōu)先級,,即threadPriority。那么執(zhí)行main的時候,,線程優(yōu)先級就會調(diào)整到所設(shè)置的線程優(yōu)先級,。這個默認值是0.5,我們可以在Operation執(zhí)行前修改它,。

  1. operation.threadPriority = 0.1; 

注意:如果你重載的start方法,,那么你需要自己來配置main執(zhí)行時的線程優(yōu)先級和threadPriority字段保持一致。

 

Operation狀態(tài)變化

我們可以通過KVO機制來監(jiān)聽Operation的一下狀態(tài)改變,,比如一個Operation的執(zhí)行狀態(tài)或完成狀態(tài),。這些狀態(tài)的keypath包括以下幾個:

  • isCancelled
  • isConcurrent
  • isExecuting
  • isFinished
  • isReady
  • dependencies
  • queuePriority
  • completionBlock

NSOperationQueue

NSOperationQueue是一個Operation執(zhí)行隊列,你可以將任何你想要執(zhí)行的Operation添加到Operation Queue中,,以在隊列中執(zhí)行,。同時Operation和Operation Queue提供了很多可配置選項,。Operation Queue的實現(xiàn)中,,創(chuàng)建了一個或多個可管理的線程,為隊列中的Operation提供可高度自定的執(zhí)行環(huán)境,。

 

Operation的依賴關(guān)系

有時候我們對任務(wù)的執(zhí)行順序有要求,,一個任務(wù)必須在另一個任務(wù)執(zhí)行之前完成,這就需要用到Operation的依賴(Dependency)屬性。我們可以為每個Operation設(shè)定一些依賴的另外一些Operation,,那么如果依賴的Operation沒有全部執(zhí)行完畢,,這個Operation就不會被執(zhí)行。

  1. [operation addDependency:anotherOperation]; 
  2. [operation removeDependency:anotherOperation]; 

如果將這些Operation和它所依賴的Operation加如隊列中,,那么Operation只有在它依賴的Operation都執(zhí)行完畢后才可以被執(zhí)行,。這樣我們就可以方便的控制Operation執(zhí)行順序。

 

Operation在隊列中執(zhí)行的優(yōu)先級

Operation在隊列中默認是按FIFO(First In First Out)順序執(zhí)行的,。同時我們可以為單個的Operation設(shè)置一個執(zhí)行的優(yōu)先級,,打亂這個順序。當Queue有空閑資源執(zhí)行新的Operation時,,會優(yōu)先執(zhí)行當前隊列中優(yōu)先級最高的待執(zhí)行Operation,。

 

最大并發(fā)Operation數(shù)目

在一個Operation Queue中是可以同時執(zhí)行多個Operation的,Operation Queue會動態(tài)的創(chuàng)建多個線程來完成相應(yīng)Operation,。具體的線程數(shù)是由Operation Queue來優(yōu)化配置的,,這一般取決與系統(tǒng)CPU的性能,比如CPU的核心數(shù),,和CPU的負載,。但我們還是可以設(shè)置一個最大并發(fā)數(shù)的,那么Operation Queue就不會創(chuàng)建超過最大并發(fā)數(shù)量的線程,。

  1. NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
  2. queue.maxConcurrentOperationCount = 1; 

 

如果我們將maxConcurrentOperationCount設(shè)置為1,,那么在隊列中每次只能執(zhí)行一個任務(wù)。這就是一個串行的執(zhí)行隊列了,。

 

Simple Code

下面我寫了一個簡單的Simple Code來說明一下Operation和Operation Queue,。

  1. NSBlockOperation *operation5s = [NSBlockOperation blockOperationWithBlock:^{ 
  2.     NSLog(@"operation5s begin"); 
  3.     sleep(5); 
  4.     NSLog(@"operation5s end"); 
  5. }]; 
  6. operation5s.queuePriority = NSOperationQueuePriorityHigh; 
  7. NSBlockOperation *operation1s = [NSBlockOperation blockOperationWithBlock:^{ 
  8.     NSLog(@"operation1s begin"); 
  9.     sleep(1); 
  10.     NSLog(@"operation1s end"); 
  11. }]; 
  12. NSBlockOperation *operation2s = [NSBlockOperation blockOperationWithBlock:^{ 
  13.     NSLog(@"operation2s begin"); 
  14.     sleep(2); 
  15.     NSLog(@"operation2s end"); 
  16. }]; 
  17.  
  18. operation1s.completionBlock = ^{ 
  19.     NSLog(@"operation1s finished in completionBlock"); 
  20. }; 
  21.  
  22. NSOperationQueue *queue = [[NSOperationQueue alloc] init]; 
  23. queue.maxConcurrentOperationCount = 1; 
  24. [queue addOperation:operation1s]; 
  25. [queue addOperation:operation2s]; 
  26. [queue addOperation:operation5s]; 
  27. [queue waitUntilAllOperationsAreFinished]; 

運行這段代碼,我得到了一下輸出結(jié)果:

  1. operation1s begin 
  2. operation1s end 
  3. operation5s begin 
  4. operation1s finished in completionBlock 
  5. operation5s end 
  6. operation2s begin 
  7. operation2s end 

 

為了更好的展示隊列優(yōu)先級效果,,我把queue的maxConcurrentOperationCount設(shè)置為1,,以便任務(wù)一個一個的執(zhí)行。從上面日志可以看出,,第一個operation1s執(zhí)行完畢后,,會執(zhí)行operation5s,而不是operation2s,,因為operation5s的queuePriority是NSOperationQueuePriorityHigh,。而第一個線程總是會第一個執(zhí)行。在看看2-4行,,我們可以看出operation1s的completionBlock比operation5s晚開始執(zhí)行,,說明它不在operation1s的線程中執(zhí)行的。正如前面所說,,completionBlock是通過KVO監(jiān)聽執(zhí)行,,一般會運行在監(jiān)聽所在線程,而不是Operation執(zhí)行的線程。

 

注意事項

當一個Operation被加入Queue中后,,請不要對這個Operation再進行任何修改,。因為一旦加入Queue,它隨時就有可能會被執(zhí)行,,對它的任何修改都有可能導致它的運行狀態(tài)不可控制,。

 

threadPriority僅僅影響了main執(zhí)行時的線程優(yōu)先級,其他的方法包括completionBlock都是以默認的優(yōu)先級來執(zhí)行的,。如果自定義的話,,也要注意在main執(zhí)行前設(shè)置好threadPriority,執(zhí)行完畢后要還原默認線程優(yōu)先級,。

 

經(jīng)測試,,Operation的threadPriority字段只有在Operation單獨執(zhí)行時有效,在Operation Queue中是無效的,。

 

第一個加入到Operation Queue中的Operation,,無論它的優(yōu)先級有多么低,總是會第一個執(zhí)行,。

 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導購買等信息,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多