iOS多線程編程之Operation Queues

相對于GCD來說,Operation Queues會更加復雜一些,但是可以為operation之間添加依賴關(guān)系、暫停和恢復Operation Queue、取消正在執(zhí)行的operation。這是GCD所做不到的。

Operation

要使用Operation Queue技術(shù),需要使用NSOperation類來封裝需要執(zhí)行的任務。但是,NSOperation本身不能實例化,所以必須使用系統(tǒng)本身就實現(xiàn)好的兩個子類:NSInvocationOperationNSBlockOperation,或者自己創(chuàng)建一個NSOperation的子類。

NSInvocationOperation

使用- (nullable instancetype)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;創(chuàng)建一個NSInvocationOperation對象。這個對象可以隨時更換SEL,例如:

operation.invocation.selector = @selector(operationMethod:);

NSBlockOperation

使用+ (instancetype)blockOperationWithBlock:(void (^)(void))block;創(chuàng)建一個NSBlockOperation對象。

自定義NSOperation

必須重寫的方法:

  1. - (void)start 是一個operation的起點。
  2. - (BOOL)isConcurrent 是否是并發(fā)的,返回YES
  3. - (BOOL)isExecuting 是否開始執(zhí)行;
  4. - (BOOL)isFinished 是否執(zhí)行完成;
    其中第3、4個方法所代表的屬性值發(fā)生變化時,我們需要手動觸發(fā)KVO通知,以便外界能觀察到這些值的變化。例如:
[self willChangeValueForKey:@"isFinished"];
_isFinished = YES;
[self didChangeValueForKey:@"isFinished"];

</br>
注意:為了支持operation的取消操作,在執(zhí)行操作時要定期檢查isCancelled的值,一旦返回YES則立刻停止之后的操作。當然也可以自己重寫- (void)cancel方法來取消正在執(zhí)行的操作,不過要記得調(diào)用[super cancel]

CompletionBlock

使用setCompletionBlock: 方法設置operation的CompletionBlock
從字面意思上看很容易理解CompletionBlock的作用,但是值得一提的是,當一個operation調(diào)用了cancel方法取消后,也會執(zhí)行CompletionBlock,所以需要在block中判斷operation是否被取消。

添加依賴關(guān)系

使用NSOperation對象的兩個方法:

- (void)addDependency:(NSOperation *)op;
- (void)removeDependency:(NSOperation *)op;

為operation添加依賴關(guān)系。例如:[A addDependency:B] 表示A依賴于B,所以A需要等B執(zhí)行完后才會開始執(zhí)行。
注意:兩個有依賴關(guān)系的operation不一定需要在同一個OperationQueue對象之中。

設置Operation在隊列中的優(yōu)先級

NSOperation對象使用setQueuePriority:設置自身在NSOperationQueue對象中執(zhí)行的優(yōu)先級。參數(shù)有:

typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
    NSOperationQueuePriorityVeryLow = -8L,
    NSOperationQueuePriorityLow = -4L,
    NSOperationQueuePriorityNormal = 0,
    NSOperationQueuePriorityHigh = 4,
    NSOperationQueuePriorityVeryHigh = 8
};

執(zhí)行Operation

Operation對象有兩種執(zhí)行方式:

  1. 直接讓對象調(diào)用- (void)start;方法,但是這種方式并不能保證Operation對象是異步執(zhí)行的;
  2. 將Operation對象放入NSOperationQueue對象中,讓NSOperationQueue的對象幫我們自動執(zhí)行,OperationQueue會自動為這個 operation創(chuàng)建一個線程,不需要我們自己去實現(xiàn)異步執(zhí)行。

取消Operation

使用NSOperation對象調(diào)用它的cancel方法取消這個 operation ,或者調(diào)用 NSOperationQueue對象的 cancelAllOperations方法取消這個OperationQueue 中所有的operation。
注意:一般情況下正在執(zhí)行中的operation需要等到下一個檢查isCancelled的位置才會停止,所以最好設置CompletionBlock來判斷operation的isCancelled的值再決定是否執(zhí)行operation完成后的操作。
例如:在一個根據(jù)用戶實時輸入的文字來進行搜索并展示返回結(jié)果的案例中,因為operation是并發(fā)的,假如用戶先后輸入了ABC,而返回的結(jié)果的順序不一定是AABABC,所以最后展示的結(jié)果不一定是ABC的搜索結(jié)果,解決方法就是在用戶輸入文字后取消之前的operation,而在CompletionBlock中判斷isCancelled的值,只有沒被取消再使用主線程更新UI。

暫停和恢復OperationQueue

使用NSOperationQueue對象調(diào)用setSuspended: 來實現(xiàn)暫停或恢復OperationQueue,不過正在執(zhí)行的Operation并不能暫停,除非直接取消Operation。
</br>
想更深入的了解Operation Queues可以查看AFNetworkingAFURLConnectionOperation代碼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容