定義:NSOperation,是OC對象,內部封裝了GCD,可以實現管理隊列的操作,如果開發中不需要管理這些隊列,那麼使用GCD就足夠了
//操作 (NSOperation是抽象類,不能直接調用,而是用兩個子類)
1、NSInvocationOperation
2、NSBlockOperation
//也可以通過重寫NSOperation的main方法來達到自定義操作
注意: NSBlockOperaion 如果追加了任務,直接啓動操作/或者將操作添加到主隊列,都不能保證操作中的任務是在主線程執行!任務在哪條線程執行不確定!開發中要避免往 NSBlockOperation 中追加任務!放到非主隊列中執行沒有問題!
以下是相關方法
- (void)start; //在當前任務狀態和依賴關係合適的情況下,啓動NSOperation的main方法任務,需要注意缺省實現只是在當前線程運行。如果需要併發執行,子類必須重寫這個方法,並且使 - (BOOL)isConcurrent 方法返回YES
- (void)main; //定義NSOperation的主要任務代碼
- (BOOL)isCancelled; //當前任務狀態是否已標記爲取消
- (void)cancel; //取消當前NSOperation任務,實質是標記isCancelled狀態
- (BOOL)isExecuting; //NSOperation任務是否在運行
- (BOOL)isFinished; //NSOperation任務是否已結束
NSOperation其它常用方法,包括依賴關係:
- (BOOL)isReady; //是否能準備運行,這個值和任務的依賴關係相關
- (void)addDependency:(NSOperation *)op; //加上任務的依賴,也就是說依賴的任務都完成後,才能執行當前任務
- (void)removeDependency:(NSOperation *)op; //取消任務的依賴,依賴的任務關係不會自動消除,必須調用該方法
- (NSArray *)dependencies; //得到所有依賴的NSOperation任務
以及用於任務同步:
- (void)waitUntilFinished; //阻塞當前線程,直到該NSOperation結束。可用於線程執行順序的同步
- (void)setCompletionBlock:(void (^)(void))block; //設置NSOperation結束後運行的block代碼,由於NSOperation有可能被取消,所以這個block運行的代碼應該和NSOperation的核心任務無關。
除了繼承NSOperation來實現併發代碼,通常更簡便的辦法是使用它的兩個子類NSInvocationOperation或NSBlockOperation,然後加入到NSOperationQueue執行隊列中去運行。部分示例代碼如下:
NSInvocationOperation *opA = [[NSInvocationOperationalloc]initWithTarget:self selector:@selector(operate) object:nil];
NSBlockOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
[self operate];
}];
- (void)operate
{
//thread loop
while (condition)
{
//....
}
}
NSOperationQueue *queue = [[NSOperationQueuealloc] init];
queue.maxConcurrentOperationCount = 2; //設置最大併發執行數,如果爲1則同時只有一個併發任務在運行,可控制順序執行關係
[queue addOperation:opA]; //加入到執行隊列中,如果isReady則開始執行
[queue addOperation:opB]; //同上,需要注意這時opA和opB是在併發運行
[queue waitUntilAllOperationsAreFinished]; //當前線程等待,直到opA和opB都執行結束
如果要求opB在opA執行完成後纔開始執行,需要加上依賴關係即可:
[opB addDependency:opA];
當然也可以使用同步方法waitUntilFinished,在前面的例子中加入:
NSBlockOperation *opB = [NSBlockOperation blockOperationWithBlock:^{
[opA waitUntilFinished]; //opB線程等待直到opA執行結束(正常結束或被取消)
[self operate];
}];
建立依賴關係或等待關係,一定要出現避免循環依賴或循環等待,否則就會造成線程死鎖。
最後看看NSOperationQueue的其它常用方法:
- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait; //批量加入執行operation,wait標誌是否當前線程等到所有operation結束
- (void)addOperationWithBlock:(void (^)(void))block; //相當於加入一個NSBlockOperation執行任務
- (NSArray *)operations; //返回已加入執行operation的數組,當某個operation結束後會自動從這個數組清除
- (NSUInteger)operationCount //返回已加入執行operation的數目
- (void)setSuspended:(BOOL)b; //是否暫停將要執行的operation,但不會暫停已開始的operation
- (BOOL)isSuspended; //返回暫停標誌
- (void)cancelAllOperations; //取消所有operation的執行,實質是調用各個operation的cancel方法
+ (id)currentQueue; //返回當前NSOperationQueue,如果當前線程不是在NSOperationQueue上運行則返回nil
+ (id)mainQueue; //返回主線程的NSOperationQueue,缺省總是有一個queue