iOS線程淺析

來源:互聯網
上載者:User


一、線程概述

1、 iOS裡面的線程按種類可分為同步線程和非同步線程。同步線程指調用同步線程的地方必須等到同步線程執行完畢才可以繼續向下執行。而調用非同步線程的地方則在執行完調用非同步線程的語句後就可以繼續向下執行。

2、線程按調用方式又可以大致分為以下幾種類型:NSObject、NSThread、NSOperation和GCD。NSObject和NSThread只能管理單個的線程,功能較簡單,GCD和NSOperation則可以進行隊列等複雜操作,且效率較高。其中GCD方式最為有效,NSOperation是基於GCD封裝的,功能相對來說更豐富。

3、非同步線程中往往要建立自己的自動釋放池來釋放非同步線程中建立的自動釋放對象。

4、非同步線程中有需要的話,要做自己的異常捕捉處理,因為當非同步線程中產生異常時,主線程很有可能會捕捉不到非同步線程拋出的異常。


二、線程調用

1、NSObject

* 線程建立

NSObjcet對象自身實現了performSelectorInBackground、performSelectorOnMainThread和performSelector:onThread:withObject:等線程相關方法。


1.1 performSelectorInBackground是建立一個非同步線程

-(void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait :

aSelector是在主線程中執行的方法,arg是傳遞的參數,wait指是否要等待aSelector執行完畢。


1.2 performSelectorOnMainThread是返回主線程執行相關方法

-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait:

aSelector是在主線程中執行的方法,arg是傳遞的參數,wait指是否要等待aSelector執行完畢。


1.3 performSelector:onThread:withObject:是執行某個特定線程中的方法

-(void)performSelector:(SEL)aSelector onThread:(NSThread *) withObject:(id)arg waitUntilDone:(BOOL)wait:

該方法一般用於線程間相互連信,即在一個線程中發送訊息給另一個線程

註:每一個線程都有自己的RunLoop,但非主線程的RunLoop預設是關閉的,當需要進行非主線程的通訊時,需要確保通訊線程的RunLoop是開啟的,否則發送給通訊線程的訊息不會被執行。


1.4 -(void)performSelector:withObject:afterDelay:是指在當前線程順延強制某個方法

* 線程的暫停、繼續和取消

NSObject是無法暫停和取消線程的。


2、NSThread

* 線程建立

NSThread有兩種建立線程的方式: detachNewThreadSelector和initWithTarget.

2.1 detachNewThreadSelector:toTarget: withObject:

調用這種方法建立的線程會主動運行,不需要手動啟動。

2.2 initWithTarget: selector:objcet:

調用這種方式建立一個線程,建立完成後需要調用NSThread的start方法來啟動線程。


* 線程的取消

調用NSThrea的cancel方法即可取消線程,但正在執行的線程不會馬上結束。所以NSThread的cancel方法的實質意義是把線程的狀態設定為已取消,然後編代碼時就可以依賴線程的狀態去結束掉線程。


* 線程的暫停和繼續

NSThread沒有提供暫停方法


3、NSOperation

* 線程建立

NSOperation通常和NSOperationQueue配對使用,建立好NSOperation對象後添加到NSOperationQueue中,NSOperationQueue即可為我們管理NSOperation,包括為NSOperation配置非同步線程和啟動等。


NSOperationQueue按類型分為:主隊列和自訂隊列。主隊列運行在主線程上,而自訂隊列在後台執行。主隊列擷取方式:[NSOperationQueue mainQueue];自訂隊列擷取方式:[[NSOperationQueue alloc] init]。


NSOperation按類型分為:NSOperation、NSBlockOperation和NSInvocationOperation。


3.1 NSOperation:

NSOperation是一個虛類,我們需要繼續NSOperation來建立子類,並重寫main方法或start方法。重寫main方法很簡單,只需要重寫好main方法,不需要管理一些狀態屬性(如isExecuted和isFinished),當main方法返回就假定操作結束了;而重寫start方法則更靈活,擁有更多的控制權,但是狀態屬性資訊則需要自己控制。


3.2 NSBlockOperation:

NSBlockOperation是調用blockOperationWithBlock方法以一個block作為參數建立的一個operation對象,並且在對象執行個體化後還可以調用addExecutionBlock方法動態添加block,但添加動作需要在operation執行前發生,通常也就是在operation添加到NSOperationQueue前,否則很可能產生異常和莫名錯誤。NSBlockOperation的商務邏輯操作主要寫在block中。


3.3 NSInvocationOperation:

NSInvocationOperation是以一個SEL方法或NSInvocation為參數初始化的operation對象。NSInvocationOperation的商務邏輯操作主要放在對應的SEL方法或NSInvocation對象中。


* 線程的暫訂和繼續

調用NSOperationQueue對象的setSuspended:YES即可暫停NSOperationQueue中待執行線程的執行,然後調用setSuspended:NO即可繼續執行。


* 線程的取消

調用NSOperation對象的cancel方法會取消單個NSOperation對象的執行,而調用NSOperationQueue對象的cancelAllOperation方法會取消NSOperation隊列中所有對象的執行。


* 線程依賴

如果NSOperation對象有執行順利要求的話,比如operationB需要在operationA執行完畢後才可以執行,那就可以通過設定NSOperation之間的依賴關係來實現:[operationB addDependency:operationA]。


* 手動執行

如果NSOperation不和NSOperationQueue配對使用,這時就需要調用NSOperation的start方法來執行NSOperation,通常要重寫isExecuting,isFinished,start和main等方法,如果要實現並行作業,則還要重寫isConcurrent方法,如果NSOperation間有依賴關係,則還要重寫isReady方法。樣本如下:


@interface HandOperation(){

BOOL executing; // 是否正在執行

BOOL finished;// 是否執行結束

}

-(void)completeOperation;// 結束後的狀態處理方法

@end


@implementation HandOperation

#pragma mark - Lifecycle Methods

-(id)init{

self = [super init];

if(self){

executing = NO;

finished = NO;

}

return self;

}

-(BOOL)isConcurrent{

return YES;

}


-(BOOL)isExecuting{

return executing;

}


-(BOOL)isFinished{

return finished;

}


-(BOOL)isReady{

return [super isReady];

}


-(void)start{

if([self isCancelled]){

[self willChangeValueForKey:@“isFinished”];

finished = YES;

[self didChangeValueForKey:@“isFinished”];

return;

}

[self willChangeValueForKey:@“isExecuting”];

executing = YES;

[NSThread detachNewThreadSelector:@selector(main) toTarget:self withObject:nil];

[self didChangeValueForKey:@“isExecuting”];

}


-(void)main{

@try{

@autoraleasepool{

[self handleForTask];

}

[self completeOperation];

}

@catch(NSException *exception){


}

@finally{


}

}


#pragma mark - Custom Methods

-(void)completeOperation{

[self willChangeValueForKey:@“isFinished”];

[self willChangeValueForKey:@“isExecuting”];

executing = NO;

finished = YES;

[self didChangeValueForKey:@“isExecuting”];

[self didChangeValueForKey:@“isFinished”];

}


//業務處理方法

-(void)handleForTask{

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

if(![self isCancelled]){

NSLog(@“%s %i”,__func__,i);

sleep(1);

}

}

}


4、GCD

* 線程建立

GCD是Grand Central Dispatch的縮寫,是Apple開發的一個多核編程的解決方案。GCD通常是把block以dispatch_async或dispatch_sync的方式添加到dispatch_queue_t隊列中來建立線程: dispatch_async(dispatch_queue_t queue ,dispatch_block block)。

dispatch_async為非同步添加,等dispatch_async語句執行完畢後即可繼續執行下去;而dispatch_sync為同步添加,需要等dispatch_sync添加的block內容執行完畢後才可以繼續向下執行。

dispatch_queue_t分為三種類型: Serial Queues、Main Queues和Concurrent Queues。


4.1 Serial Queues

Serial Queues稱為串列隊列,Serial Queues隊列中的任務只能順序執行,一次執行一個。我們可以在Serial Queues中執行有依賴關係的任務或同步任務。

Serial Queues隊列之間是可以並發執行的。

Serial Queues是通過dispatch_queue_create(“testQueue”,NULL)語句建立的,“testQueue”是隊列標識符,NULL對應一個表示隊列屬性的參數,只要傳入NULL或DISPATCH_QUEUE_SERIAL即可擷取一個串列隊列。


4.2 Main Queues

Main Queues 稱為主線程隊列,所有提交至Main Queues中的任務都會在主線程中執行,所以Main Queues也是一個串列隊列。

Main Queues可以通過dispatch_get_main_queue()語句擷取到,Main Queues是全域性的隊列。


4.3 Concurrent Queues

Concurrent Queues稱為並行隊列,所有提交至Concurrent Queues中的任務都是並存執行的。Concurrent Queues又分為Global Queues和User Concurrent Queues。Global Queues由系統根據優先順序提供四個不同的dispatch queue。

Global Queues可以通過dispatch_get_global_queue(dispatch_queue_priority_t priority,unsigned long flags)語句擷取到,priority是優先順序,優先順序有DISPATCH_QUEUE_PRIORITY_HIGH、DISPATCH_QUEUE_PRIORITY_DEFAULT、DISPATCH_QUEUE_PRIORITY_LOW、DISPATCH_QUEUE_PRIORITY_BACKGROUND四種:flags是保留欄位,現階段傳入0即可。


User Concurrent Queues是通過dispatch_queue_create(“testQueue”,DISPATCH_QUEUE_CONCURRENT)語句建立的,“testQueue”是隊列標識符,DISPATCH_QUEUE_CONCURRENT表示隊列為並行隊列。


* 線程的暫停和繼續

調用dispatch_suspend(dispatch_queue_t)即可掛起隊列,使隊列中待執行的任務暫停執行,但正在執行的任務還是會繼續執行。

調用dispatch_resume(dispatch_queue_t)即可以使掛起的隊列繼續執行。

dispatch_suspend 和 dispatch_resume只對Serial Queues 和 User Concurrent Queues有效,因為Main Queues 和Global Queues都是全域隊列。


* 線程的取消

GCD中沒有顯式的線程取消方法調用,只能在代碼中根據預先設定的標誌位去實現取消操作。


* dispatch_group_async的使用

dispatch_group_async可以實現監聽一組任務是否完成,完成後得到通知執行其他動作。

使用dispatch_group_async添加一組任務後,可以使用dispatch_group_wait方法同步等待全部任務執行完畢,然後才執行之後的其他任務;也可以使用dispatch_group_notify非同步監聽前面的任務,等前面任務執行完畢後觸發dispatch_group_notify中的處理事件。如下:


dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_group_t group = dispatch_group_create();

dispatch_group_async(group,globalQueue,^{

@autoreleasepool{

for(int i=0;i<5;i++){

NSLog(@“001 %i”,i);

sleep(1);

}

}

});

dispatch_group_async(group,globalQueue,^{

@autoreleasepool{

for(int i=0;i<5;i++){

NSLog(@“002 %i”,i);

sleep(1);

}

}

});


dispatch_group_wait(group,DISPATCH_TIME_FOREVER);


/*

dispatch_group_notify(group,globalQueue,^{

@qutoreleasepool{

NSLog(@“notify End”);

}

});

*/

dispatch_release(group);


* dispatch_barrier_async的使用

dispatch_barrier_async是在前面的任務執行結束後它才執行,而且它後面的任務等它執行完成後才執行。

dispatch_barrier_async(dispatch_queue_t queue,dispatch_block_t block),queue必須是自訂的並行隊列,如果是其他隊列,那麼dispatch_barrier_async的效果和dispatch_sync是相同的。


* dispatch_apply 的使用

dispatch_apply可以執行某個程式碼片段N次,可以用在相互間沒依賴關係的並行計算等。代碼如下:

dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_PRIORITY_DEFAULT,0);

__block int sum = 0;

dispatch_apply(10,globalQueue,^(size_t i){

sum += i;

});




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.