標籤:ios 線程
接上一篇
2、NSOperation
NSOperation是一個抽象類別,本身並沒有辦法去直接使用,如果我們要使用它,就要去使用它的子類。IOS已經給我們提供了兩個已經實現好的子類,NSInvocationOperation和NSBlockOperation。
對於這兩個子類雖然IOS本身提供了start方法,不過我們一般不去直接使用它而需要藉助另外一個類 NSOperationQueue 。
NSOperationQueue顧名思義是一個操作隊列,他會給我們提供一個有序的執行隊列,看一下蘋果官方對這個類的描述
The NSOperationQueue class regulates the execution of a set of NSOperation objects. After being added to a queue, an operation remains in that queue until it is explicitly canceled or finishes executing its task. Operations within the queue (but not yet executing) are themselves organized according to priority levels and inter-operation object dependencies and are executed accordingly. An application may create multiple operation queues and submit operations to any of them.Inter-operation dependencies provide an absolute execution order for operations, even if those operations are located in different operation queues. An operation object is not considered ready to execute until all of its dependent operations have finished executing. For operations that are ready to execute, the operation queue always executes the one with the highest priority relative to the other ready operations. For details on how to set priority levels and dependencies, see NSOperation Class Reference.You cannot directly remove an operation from a queue after it has been added. An operation remains in its queue until it reports that it is finished with its task. Finishing its task does not necessarily mean that the operation performed that task to completion. An operation can also be canceled. Canceling an operation object leaves the object in the queue but notifies the object that it should abort its task as quickly as possible. For currently executing operations, this means that the operation object’s work code must check the cancellation state, stop what it is doing, and mark itself as finished. For operations that are queued but not yet executing, the queue must still call the operation object’s start method so that it can processes the cancellation event and mark itself as finished.
大概意思是 NSOperationQueue類調節一組的NSOperation對象的執行。在隊列中的NSOperation對象會按照絕對的順序去執行,也就是說當任務加入到任務隊列後,會自動按照優先順序和依賴關係自動運行。
還是上面的例子
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib.// NSThread *mThread = [[NSThread alloc] initWithTarget:self selector:@selector(DownImage:) object:IMAGE_PATH];// [mThread start]; NSInvocationOperation *mOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(DownImage:) object:IMAGE_PATH];// [mOperation start]; NSOperationQueue *mQueue = [[NSOperationQueue alloc] init]; [mQueue addOperation:mOperation];}
看上去很簡單,僅僅就是建立任務,然後加入到隊列。這個隊列是個任務的pool,遵循生產者-消費者的關係,當有任務的時候會自動運行任務。我們可以使用setMaxConcurrentOperationCount:這個方法來設定這個queue裡面的線程總數,預設值是-1,意思是沒有限制。
在繼承NSOperation後,對於非並發的工作,需要實現NSOperation子類的main方法:
-(void)main
{
@try
{
// 處理工作任務
}
@catch(…)
{
// 處理異常,但是不能再重新拋出異常
}
}
因為NSOperation的任務是可以cancel的,所以在main方法處理任務時就要不斷輪詢isCancelled。另外,這個main方法本來是空的,所以不需要調用[super main]這句。
還有一個start方法,這個start方法是工作的入口,通常是用來設定線程需要的運行環境的。和main一樣,不要調用[super start]。這個方法還會區分這個啟動並執行狀態,如果是canceled或者已經結束了,這個任務就不會運行;而如果是正在運行或者還沒ready,則會扔出一個異常。
如果要支援並發任務,至少需要重寫start、isConcurrent、isExecuting、isFinished四個方法。這裡需要說一下這個isConcurrent方法,這個方法是標誌operation是否並存執行的,如果是concurrent的,則返回YES;反之,則返回NO。如果沒有重寫這個方法,則預設NO,但在OS X10.6之後,這個值被忽略了。
另外,NSOperation的一些屬性是支援KVC的,我們可以通過KVO方法來觀察這些屬性並在應用的其他地方來控製程序運行,所以需要在合適的時候發出KVO通知。
NSOperation支援的KVO屬性有:isCancelled、isConcurrent、isExecuting、isFinished、isReady、dependencies、queuePriority、completionBlock。如果你增加了屬性,推薦同樣支援KVC和KVO。
IOS中的線程操作(2)