iOS_多線程三:NSOperation的使用

NSOperation 是一個抽象類,線程安全,不需要添加額外的鎖

使用其子類:NSInvocationOperation 和 NSBlockOperation

1、NSInvocationOperation

一個對象,表示一個任務

默認在主線程中同步順序執行,想要併發異步,需要搭配`NSOperationQueue`使用

同步/異步,通過設置最大併發數`maxConcurrentOperationCount`實現:1:同步 >=2:異步 默認:-1 異步(無窮大)

    

2、NSBlockOperation

一個對象,可以創建多個任務

blockOperationWithBlock 添加的任務默認在主線程中

addExecutionBlock 添加任務,會開啓多個線程,併發執行

 

一、NSInvocationOperation

一個 NSInvocationOperation 對象表示一個任務,需要手動調用 start 開啓。

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(network:) object:@{@"name":@"moxiaohui"}];
[operation setName:@"moxiaoyan"];
[operation setCompletionBlock:^{ // 任務執行完成後在子線程中執行
  NSLog(@"Completion %@", [NSThread currentThread]);
}];
[operation start];
NSLog(@"是否阻塞主線程"); // 會

- (void)network:(NSDictionary *)info {
  NSLog(@"執行 operation %@ %@", [NSThread currentThread], info);
  sleep(2);
  NSLog(@"完成 operation");
}

// 執行結果:
// 執行 operation <NSThread: 0x600000c24040>{number = 1, name = main} {
    name = moxiaohui;
}
// 完成 operation
// 是否阻塞主線程
// Completion <NSThread: 0x600003139680>{number = 4, name = (null)}

從執行結果可以看得出來,默認是在主線程中執行的,而且會阻塞主線程。

若想實現異步併發,需要結合 NSOperationQueue 使用:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 設置最大併發數: 1:同步 >=2:異步  默認:-1(無窮大)
// 注意:設置的是隊列裏面最多能併發運行的操作任務個數,而不是線程個數, (另外開啓線程的數量是由系統決定的,所以這個值具體表示什麼?)
[queue setMaxConcurrentOperationCount:2];
// 將任務添加到隊列中
[queue addOperation:operation];
NSLog(@"是否阻塞主線程");

// 執行結果:
// 是否阻塞主線程
// 執行 operation <NSThread: 0x6000005e44c0>{number = 5, name = (null)} {
    name = moxiaohui;
}

NSOperationQueue一些其他的屬性和方法:

// 可以設置特殊的先後執行順序:addDependency
[operation2 addDependency:operation1]; // 添加依賴
[operation3 removeDependency:operation1]; // 移除依賴

[operation start];  // NSInvocationOperation alloc init 創建的需要手動開啓
[operation cancel]; // 取消單個任務,只會對還未執行的任務有效
[operation waitUntilFinished]; // 阻塞當前線程,直到任務執行完畢後繼續 (最好不要在主線程中等待,會阻塞)
// 觀察任務狀態:
[operation isReady];  // 是否就緒
[operation isExecuting]; // 是否正在執行中
[operation isFinished]; // 是否執行完畢
[operation isCancelled];  // 是否已取消
[operation isAsynchronous]; // 是否異步執行
[operation isConcurrent]; // 已廢棄,用`isAsynchronous`
NSOperationQueuePriority priority = [operation queuePriority]; // 優先級
NSArray<NSOperation *> *dependencies = [operation dependencies]; // 依賴的任務數組

二、NSBlockOperation

NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{ // 默認在主線程中
  NSLog(@"執行2 block %@", [NSThread currentThread]);
  sleep(1);
  NSLog(@"完成2 block");
}];

// 通過 addExecutionBlock 添加的任務,會開闢多個子線程
[block addExecutionBlock:^{
  NSLog(@"執行3 block %@", [NSThread currentThread]);
  sleep(1);
  NSLog(@"完成3 block");
}];
[block addExecutionBlock:^{
  NSLog(@"執行4 block %@", [NSThread currentThread]);
  sleep(3);
  NSLog(@"完成4 block");
}];
[block addExecutionBlock:^{
  NSLog(@"執行5 block %@", [NSThread currentThread]);
  sleep(2);
  NSLog(@"完成5 block");
}];
[block start];
NSLog(@"是否阻塞主線程"); // 會

// 執行結果:
// 執行3 block <NSThread: 0x600003a9cd80>{number = 5, name = (null)}
// 執行2 block <NSThread: 0x600003a982c0>{number = 6, name = (null)}
// 執行5 block <NSThread: 0x600003aced40>{number = 1, name = main}
// 執行4 block <NSThread: 0x600003a97740>{number = 3, name = (null)}
// 完成2 block
// 完成3 block
// 完成5 block
// 完成4 block
// 是否阻塞主線程

從執行結果可以看出來,任務一多,就不確定哪個任務會主線程中執行了,所以感覺還是用queue比較保險

三、NSOperationQueue

NSOperationQueue 操作隊列,管理Operation對象,根據Operation開闢適量的線程

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 設置最大併發數: 1:同步 >=2:異步  默認:-1(無窮大)
// 注意:設置的是隊列裏面最多能併發運行的操作任務個數,而不是線程個數, (另外開啓線程的數量是由系統決定的,所以這個值具體表示什麼?)
[queue setMaxConcurrentOperationCount:2];
// 將任務添加到隊列中
[queue addOperation:operation];
NSLog(@"是否阻塞主線程");
[queue addOperation:block];
[queue addOperationWithBlock:^{
NSLog(@"執行6 %@", [NSThread currentThread]);
sleep(2);
NSLog(@"完成6");
}];
[queue addBarrierBlock:^{ // 隊列中所有任務完成後執行
NSLog(@"all complete");
}];
[queue setSuspended:YES]; // 暫停隊列
[queue setSuspended:NO];  // 繼續隊列
[queue cancelAllOperations]; // 取消所有任務
[queue waitUntilAllOperationsAreFinished]; // 阻塞當前線程,直到所有任務執行完畢後繼續(最好不要在主線程中等待,會阻塞)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章