iOS編程中,有多種并發(fā)編程的方式,比較常見的就是基于Operation Queue和GCD,還有底層一點的NSTheard,本文主要討論Operation Queue和GCD
異步調(diào)用和并發(fā)
在談并發(fā)之前,談一談異步調(diào)用和并發(fā),異步調(diào)用是指調(diào)用時無需等待結(jié)果返回的調(diào)用。并發(fā)是指多個任務(wù)(線程)同時執(zhí)行,在異步調(diào)用的實現(xiàn)中往往用的都是并發(fā)機制,但也有可能是其他機制,比如一些依靠中斷進行的操作。(中斷:(Interrupt)是指處理器接收到來自硬件或軟件的信號,提示發(fā)生了某個事件,應(yīng)該被注意,這種情況就稱為中斷。)
Operation Queue
operation queue提供了一個面向?qū)ο蟮牟l(fā)編程接口,并支持并發(fā)數(shù)(僅operation queue支持),線程優(yōu)先級,任務(wù)優(yōu)先級,任務(wù)依賴關(guān)系等多種配置
1.面向?qū)ο蠼涌?br>
2.支持并發(fā)數(shù)配置
3.任務(wù)優(yōu)先級調(diào)度
4.任務(wù)依賴關(guān)系
5.線程優(yōu)先級配置
NSOperation簡介
在operation queue中,把每個并發(fā)任務(wù)都定義為一個operation,對應(yīng)的類名是NSOperation,NSOperation是一個抽象類,無法直接使用,它只定義了Operation的一些基本方法,我們需要創(chuàng)建一個基于他的子類或者使用系統(tǒng)預定于的子類,目前系統(tǒng)預定義了兩個子類:NSInvocationOperation和NSBlockOperation。
NSInvocationOperation
NSInvocationOperation是一個基于對象和selector的Operation,使用這個你只需要指定對象以及任務(wù)的selector,如果有必要,還可以設(shè)定傳遞的參數(shù)。
NSInvocationOperation *invacationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomethingWithObj:) object:obj];
當這個Operation完成后,你可以通過下面的方法獲得調(diào)用執(zhí)行后返回的結(jié)果對象。
id result = [invacationOperation result];
NSBlockOperation
如果不是在一個函數(shù)中執(zhí)行任務(wù),而是在一個block中執(zhí)行一個任務(wù)的話,這是我們就需要NSBlockOperation
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
//Do?something?here.
}];
運行一個Operation
[Operation start] ;
start方法用來啟動一個Operation任務(wù)。同時,Operation提供一個main方法,你的所有任務(wù)都應(yīng)該在main中進行處理。默認的start方法中會先做出一些異常判斷然后直接調(diào)用main方法。如果需要自定義一個NSOperation必須重載main方法來執(zhí)行你所想要執(zhí)行的任務(wù)。
取消一個Operation
要取消一個Operation,要發(fā)送cancel消息:
[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。
這個方法是在每一個Operation中自己用NSThread來創(chuàng)建線程,當然,這樣的行為并不是如我們所愿的
@implementation MyOperation{
BOOL????????executing;
BOOL????????finished;
}
-?(BOOL)isConcurrent?{
returnYES;
}
-?(void)start?{
if([self?isCancelled])
{
[self?willChangeValueForKey:@"isFinished"];
finished?=?YES;
[self?didChangeValueForKey:@"isFinished"];
return;
}
[self?willChangeValueForKey:@"isExecuting"];
[NSThread?detachNewThreadSelector:@selector(main)?toTarget:self?withObject:nil];
executing?=?YES;
[self?didChangeValueForKey:@"isExecuting"];
}
-?(void)main?{
@try{
//?Do?some?work.
[self?willChangeValueForKey:@"isFinished"];
[self?willChangeValueForKey:@"isExecuting"];
executing?=?NO;
finished?=?YES;
[self?didChangeValueForKey:@"isExecuting"];
[self?didChangeValueForKey:@"isFinished"];
}
@catch(...)?{
//?Exception?handle.
}
}
@end
當你自定義了start或main方法時,一定要手動的調(diào)用一些KVO通知方法,以便讓對象的KVO機制可以正常運作。