-
簡介:
NSOperation、NSOperationQueue 是蘋果提供給我們的一套多線程解決方案。實際上 NSOperation、NSOperationQueue 是基于 GCD 更高一層的封裝,完全面向對象。但是比 GCD 更簡單易用、代碼可讀性也更高。
-
NSOperation:
NSOperation有兩個子類NSInvocationOperation和NSBlockOperation,operation單獨執行start時是在主線程。
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(action:) object:@"fffffff"]; [operation start]; NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ [self action:@"222222222"]; }]; [blockOperation start];
-
NSOperationQueue:
NSOperationQueue才是真正可以異步的執行的,不過也支持同步操作。
NSOperationQueue *_operationQueue = [[NSOperationQueue alloc] init];//子線程 NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];//主線程
-
添加Operation到NSOperationQueue:
NSOperationQueue可添加三種Operation:NSInvocationOperation、NSBlockOperation、直接通過Block的方式。
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(action:) object:@"1111111"]; [_operationQueue addOperation:operation]; NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ [self action:@"222222222"]; }]; [_operationQueue addOperation:blockOperation]; [_operationQueue addOperationWithBlock:^() { [self action:@"33333333333"]; }];
-
并行/串行:
NSOperationQueue控制串行與并行很簡單,通過設置maxConcurrentOperationCount屬性即可
_operationQueue.maxConcurrentOperationCount = 1;//串行 _operationQueue.maxConcurrentOperationCount = 5;//并行
-
依賴關系:
依賴關系只決定Operation執行順序的關鍵因素。當某個NSOperation對象依賴于其它NSOperation對象的完成時,就可以通過addDependency方法添加一個或者多個依賴的對象,只有所有依賴的對象都已經完成操作,當前NSOperation對象才會開始執行操作。另外,通過removeDependency方法來刪除依賴對象。
NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ [weakSelf action:@"77777777777"]; }]; NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{ [weakSelf action:@"888888888888"]; }]; NSBlockOperation *operation3 = [NSBlockOperation blockOperationWithBlock:^{ [weakSelf action:@"99999999999"]; }]; //[operation1 addDependency:operation2]; //[operation2 addDependency:operation3]; [_operationQueue addOperation:operation1]; [_operationQueue addOperation:operation2]; [_operationQueue addOperation:operation3];
輸出如下:
//無依賴 77777777777 888888888888 99999999999 //有依賴 99999999999 888888888888 77777777777
-
優先級:
對于添加到queue中的operations,它們的執行順序取決于2點:
1.首先看看NSOperation是否已經準備好:是否準備好由對象的依賴關系確定
2.然后再根據所有NSOperation的相對優先級來確定。優先級等級則是 operation對象本身的一個屬性。默認所有operation都擁有“普通”優先級,不過可以通過setQueuePriority:方法來提升或降低operation對象的優先級。優先級只能應用于相同queue中的operations。如果應用有多個operation queue,每個queue的優先級等級是互相獨立的。因此不同queue中的低優先級操作仍然可能比高優先級操作更早執行。注意:優先級不能替代依賴關系,優先級只是對已經準備好的 operations確定執行順序。先滿足依賴關系,然后再根據優先級從所有準備好的操作中選擇優先級最高的那個執行。
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) { NSOperationQueuePriorityVeryLow = -8L, NSOperationQueuePriorityLow = -4L, NSOperationQueuePriorityNormal = 0, NSOperationQueuePriorityHigh = 4, NSOperationQueuePriorityVeryHigh = 8 }; NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ [self action:@"66666666666"]; }]; operation.queuePriority = NSOperationQueuePriorityVeryHigh;
-
取消Operation:
一旦添加到operation queue,queue就擁有了這個Operation對象并且不能被刪除,唯一能做的事情是取消。你可以調用Operation對象的cancel方法取消單個操作,也可以調用operation queue的cancelAllOperations方法取消當前queue中的所有操作。
[operation cancel];//取消單個Operation [queue cancelAllOperations]; //取消當前隊列中所有Operation
-
等待Operations:
等待在主線程是絕對不能使用的,沒有什么會比阻塞主線程更可怕的事情了。不過在一個線程中往往是要依賴另一個線程中的數據,但是另一個線程還需要時間去處理,所以等待就給我們了極大的便利。NSOperation和NSOperationQueue都可以等待
- (void)waitUntilFinishedAction { NSLog(@"------------ Wait Until Finished"); __block int number = 0; NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ [self action:@"aaaaaaaaaaa"]; number ++; }]; NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"Begain Wait"); [operation waitUntilFinished]; NSLog(@"End Wait"); if (number > 0) { NSLog(@"Good Job!"); } }]; [_operationQueue addOperation:operation1]; [_operationQueue addOperation:operation]; } - (void)waitQueueUntilFinishedAction { NSLog(@"------------ Wait Queue Until Finished Action"); NSOperationQueue *queue = [[NSOperationQueue alloc] init]; queue.maxConcurrentOperationCount = 1; [queue addOperationWithBlock:^() { [_operationQueue waitUntilAllOperationsAreFinished]; NSLog(@"Result : %d",(int)_count); }]; }
-
暫停/繼續Operations:
如果你想臨時暫停Operations的執行,可以使用queue的setSuspended:方法暫停queue。不過暫停一個queue不會導致正在執行的operation在任務中途暫停,只是簡單地阻止調度新Operation執行。你可以在響應用戶請求時,暫停一個queue來暫停等待中的任務。稍后根據用戶的請求,可以再次調用setSuspended:方法繼續queue中operation的執行
- (void)pauseAction { if (!_operationQueue.suspended) { NSLog(@"pause Action..............."); } else { NSLog(@"continue Action..............."); } [_operationQueue setSuspended:!_operationQueue.suspended]; }
-
線程間的通信:
在 iOS 開發過程中,我們一般在主線程里邊進行 UI 刷新,例如:點擊、滾動、拖拽等事件。我們通常把一些耗時的操作放在其他線程,比如說圖片下載、文件上傳等耗時操作。而當我們有時候在其他線程完成了耗時操作時,需要回到主線程,那么就用到了線程之間的通訊。
- (void)didAction { [_operationQueue addOperationWithBlock:^() { [self action:@"33333333333"]; //Main Thread __weak typeof(self) weakSelf = self; [[NSOperationQueue mainQueue] addOperationWithBlock:^{ NSLog(@"CurrentThread---%@", [NSThread currentThread]); [weakSelf setTitleLabel];//update UI }]; }]; }
-
Github實例:
這里我準備了一個模擬多線程各種操作的例子想看效果的直接下載運行吧!
https://github.com/PeaceWanghp/NSOperation.git
iOS多線程(2)-NSOperation
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
- 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
- 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
- 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
推薦閱讀更多精彩內容
- 原文鏈接:http://www.cocoachina.com/ios/20150807/12911.html 現如...