NSOperation 抽象類
- NSInvocationOperation
- NSBlockOperation
NSOpeartionQueue
* GCD 的核心概念:將任務(block)添加到隊列,並且指定執行任務的函數
* OP 的核心概念:將`操作`添加到`隊列`
NSInvocationOperation(不常用)
// 將操作添加到隊列 - 會異步
執行操作!
- (void)opDemo1 {
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo:) object:@"invocation"];
// start 會在當前線程執行 selector 方法,不會開啓線程
// [op start];
// 隊列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 將操作添加到隊列 - 會`異步`執行操作!
[queue addOperation:op];
}
隊列是一個併發
隊列
- (void)opDemo2 {
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
for (int i = 0; i < 100; ++i) {
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo:) object:@(i)];
[queue addOperation:op];
}
}
- (void)demo:(id)obj {
NSLog(@"%@ %@", [NSThread currentThread], obj);
}
NSBlockOperation(常用)
任務在子線程異步併發執行
- (void)opDemo3 {
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 操作
// 使用 block 所有的代碼可以在一起,便於閱讀和維護
for (int i = 0; i < 10; ++i) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@ %d", [NSThread currentThread], i);
}];
[queue addOperation:op];
}
}
將任務加入到一個全局隊列, 並且NSOperation的所有子類都可以加入, 異步執行
- (void)opDemo4 {
for (int i = 0; i < 10; ++i) {
[self.queue addOperationWithBlock:^{
NSLog(@"%@ %d", [NSThread currentThread], i);
}];
}
// BLOCK OPERATION
// 所有的 NSOperation 的子類,都可以添加到隊列中
// 並且都是異步執行的!
NSBlockOperation *blockOp = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"BLOCK --- %@", [NSThread currentThread]);
}];
[self.queue addOperation:blockOp];
NSInvocationOperation *inOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo:) object:@"INVOCATION"];
[self.queue addOperation:inOp];
}
線程間通訊
- (void)opDemo5 {
[self.queue addOperationWithBlock:^{
NSLog(@"耗時的操作... %@", [NSThread currentThread]);
// 在主線程更新UI
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"更新 UI %@", [NSThread currentThread]);
}];
}];
}
NSOperation的高級用法
- 最大併發數
- (void)demo {
// 設置最大併發的操作數
[self.queue setMaxConcurrentOperationCount:2];
NSLog(@"start");
for (int i = 0; i < 20; ++i) {
[self.queue addOperationWithBlock:^{
[NSThread sleepForTimeInterval:1.0];
NSLog(@"%@ %d", [NSThread currentThread], i);
}];
}
}
// 執行結果是兩個兩個一起來
- 暫停/繼續
// 暫停繼續
- (IBAction)pauseAndResume {
// 如果隊列是掛起的,再添加操作,也不會調度!
// 判斷隊列中是否有操作
if (self.queue.operationCount == 0) {
NSLog(@"沒有操作");
return;
}
// setter = !getter
// 掛起的是隊列,不會影響正在執行的操作
self.queue.suspended = !self.queue.isSuspended;
// 如果隊列中的操作沒有執行完成,操作`計數`中是包含的
if (self.queue.isSuspended) {
NSLog(@"暫停 - %tu", self.queue.operationCount);
} else {
NSLog(@"繼續 - %tu", self.queue.operationCount);
}
}
執行結果: 暫停的是隊列中的操作, 如果任務在線程中正在執行, 不會停止
- 取消全部
- (IBAction)cancelAll {
// 取消`隊列`中沒有調度的全部操作,如果正在執行的操作,不會被取消
// 提示:如果要讓正在執行的操作取消,需要自定義操作,系統提供的不行!
NSLog(@"取消全部");
[self.queue cancelAllOperations];
}
執行結果: 系統提供的無法取消線程中正在執行的操作, 只能取消隊列中等待的操作.
- 依賴關係(GCD中的依賴,可以用同步執行,barrier)
- (void)dependency {
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"用戶登錄 %@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"付費 %@", [NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下載 %@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"通知用戶 %@", [NSThread currentThread]);
}];
// 設置依賴關係 - 併發效率比GCD的串行隊列要好!
// 依賴關係,可以跨隊列指定!
// 付費需要在用戶登錄之後執行
[op2 addDependency:op1];
[op3 addDependency:op2];
[op4 addDependency:op3];
// waitUntilFinished NO 異步 YES 同步
[self.queue addOperations:@[op1, op2, op3] waitUntilFinished:NO];
// 向主隊列添加操作
[[NSOperationQueue mainQueue] addOperation:op4];
NSLog(@"come here");
}
GCD與NSOperation對比
- GCD
將任務(block)添加到隊列(串行/併發/主隊列),並且指定任務執行的函數(同步/異步)
GCD是底層的C語言構成的API
iOS 4.0 推出的,針對多核處理器的併發技術
在隊列中執行的是由 block 構成的任務,這是一個輕量級的數據結構
要停止已經加入 queue 的 block 需要寫複雜的代碼
需要通過 Barrier 或者同步任務設置任務之間的依賴關係
只能設置隊列的優先級
高級功能:
一次性 once
延遲操作 after
調度組
- NSOperation
核心概念:把操作(異步)添加到隊列(全局的併發隊列)
OC 框架,更加面向對象,是對 GCD 的封裝
iOS 2.0 推出的,蘋果推出 GCD 之後,對 NSOperation 的底層全部重寫
Operation作爲一個對象,爲我們提供了更多的選擇
可以隨時取消已經設定要準備執行的任務,已經執行的除外
可以跨隊列設置操作的依賴關係
可以設置隊列中每一個操作的優先級
高級功能:
最大操作併發數(GCD不好做)
繼續/暫停/全部取消
跨隊列設置操作的依賴關係