標籤:
1、簡介
(1) NSOperationQueue(操作隊列)是由GCD提供的隊列模型的Cocoa抽象,是一套Objective-C的API,為了使並發(多線程)編程變得更加簡單,但效率比GCD略低。在實際開發中NSOperationQueue是首選。
(2) GCD提供了更加底層的控制,而操作隊列則在GCD之上實現了一些方便的功能,這些功能對於開發人員而言通常是最好最安全的選擇。
隊列及操作
(1)NSOperationQueue有兩種不同類型的隊列:主隊列和自訂隊列
(2)主隊列運行在主線程上。
(3)自訂隊列在後台執行(只要自訂隊列,都是並發的)。
(4) NSOperation是不能直接使用的,隊列處理的任務是NSOperation的子類:
(a)NSInvocationOperation
(b)NSBlockOperation
2、NSOperation的基本使用步驟
基本使用步驟
(1) 定義操作隊列
(2) 定義操作
(3) 將操作添加到隊列
提示:一旦將操作添加到隊列,操作就會立即被調度執行
3、NSInvocationOperation(調度操作)
定義隊列:
self.myQueue = [[NSOperationQueue alloc] init];
操作調用的方法:
- (void)operationAction:(id)obj
{
NSLog(@"%@ - obj : %@", [NSThread currentThread], obj);
}
定義操作並添加到隊列:
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(operationAction:) object:@(i)];
[self.myQueue addOperation:op];
例如:
其中myQueue 為:
@property (nonatomic, strong) NSOperationQueue *myQueue;
- (void)demoOp2
{
// 需要定義一個方法,能夠接收一個參數
// 是用起來不夠靈活
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demoOp:) object:@"hello op"];
// [self.myQueue addOperation:op];//在子線程運行
[[NSOperationQueue mainQueue] addOperation:op];//在主線程運行
}
4、NSBlockOperation(塊操作)
定義操作並添加到隊列
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
[self operationAction:@"Block Operation"];
}];
將操作添加到隊列
[self.myQueue addOperation:op];
【備忘】NSBlockOperation比NSInvocationOperation更加靈活
例如:
其中myQueue 為:
@property (nonatomic, strong) NSOperationQueue *myQueue;
#pragma mark 設定任務的執行順序
- (void)demoOp3
{
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(@"更新UI %@", [NSThread currentThread]);
}];
// 設定執行順序, Dependency依賴,系統可能會開多個線程,但不會太多
// 依賴關係是可以跨隊列的!
[op2 addDependency:op1];
[op3 addDependency:op2];
[op4 addDependency:op3];
// GCD是串列隊列,非同步任務,只會開一個線程
[self.myQueue addOperation:op1];
[self.myQueue addOperation:op2];
[self.myQueue addOperation:op3];
// 所有UI的更新需要在主線程上進行,使op4在主線程執行
[[NSOperationQueue mainQueue] addOperation:op4];
}
5、設定作業的依賴關係
NSBlockOperation *op1 =
[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@ - 下載圖片", [NSThread currentThread]);
}];
NSBlockOperation *op2 =
[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@ - 添加圖片濾鏡", [NSThread currentThread]);
}];
NSBlockOperation *op3 =
[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@ - 更新UI", [NSThread currentThread]);
}];
// [op1 addDependency:op3];會造成循環相依性
[op2 addDependency:op1];
[op3 addDependency:op2];
[self.myQueue addOperation:op1];
[self.myQueue addOperation:op2];
[[NSOperationQueue mainQueue] addOperation:op3];
提示:利用addDependency可以指定操作之間的彼此依賴關係(執行先後順序)
注意:不要出現循環相依性!
6、設定同時並發的線程數量
//設定同時並發的線程數量能夠有效地降低CPU和記憶體的開銷,這一功能用GCD不容易實現。
// 建立線程是有開銷的
// 在設定同時並發的最大線程數時,如果前一個線程工作完成,但是還沒有銷毀,會建立線程
// 應用情境:網路開發中,下載工作!(線程開銷:CPU,MEM)電量!
// 如果是3G,開3個子線程
// 如果是WIFI,開6個子線程
[self.myQueue setMaxConcurrentOperationCount:2];
for (int i = 0; i < 10; ++i) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
[self operationAction:@(i)];
}];
[self.myQueue addOperation:op];
}
iOS開發之NSOperation & NSOperationQueue