上一篇文章我們已經了解過了什么是多線程,以及GCD的一些使用方法,下面繼續介紹另外一種iOS中實現多線程的方法NSOperation。
在學習這個類之前,我們還是需要知道幾個關鍵詞:
- 1.任務 : 就是你的具體操作,比如你要上傳照片、讀寫數據庫等等,都可以視為任務
- 2.隊列 : 隊列就是規定這個任務是怎么執行的,是串行,還是并行
- 3.線程:這個之前已經介紹過了,這里就不多多介紹,想了解的同學-->傳送門:iOS多線程詳細說明(GCD篇-就是個玩兒)
NSOperation
NSOperation 是個抽象類,并不具備封裝操作的能力,必須使?它的子類:NSInvocationOperation(任務)、NSBlockOperation(任務)、NSOperationQueue(隊列)
1.NSInvocationOperation(任務)
NSInvocationOperation 的作用是創建一個任務,我們來看一下具體的代碼
- (void)viewDidLoad {
[super viewDidLoad];
NSInvocationOperation *operation1 = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(operationRun) object:nil];
[operation1 start];//?< 手動開始任務
}
- (void)operationRun
{
NSLog(@"我是第一個queue%@",[NSThread currentThread]); //?< 主線程
}
這里我們值得注意的是,當這個任務沒有添加到隊列中時,默認時在當前線程中 同步 執行的,并且任務創建以后,并沒有立即執行需要我們手動開啟
2. NSBlockOperation(任務)
NSBlockOperation的作用跟NSInvocationOperation一樣,只不過NSBlockOperation創建任務的形式是以block的形式來創建的。
- (void)viewDidLoad {
[super viewDidLoad];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是block任務 %@",[NSThread currentThread]);
}];
[operation2 start];//?< 手動開始任務
}
當然NSBlockOperation的任務,也是默認在當前的線程下同步 執行,也需要我們來手動開啟
3.NSOperationQueue(隊列)
NSOperationQueue(隊列) 和GCD中的并發隊列、串行隊列略有不同的是:NSOperationQueue一共有兩種隊列:主隊列、其他隊列。其中其他隊列同時包含了串行、并發功能。下邊是主隊列、其他隊列的基本創建方法和特點。
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; //?< 主線程執行
NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init]; //?< 子線程執行
3.2將任務添加到隊列
//僅以其它隊列舉例
NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init]; //?< 子線程執行
for (NSInteger i = 0; i < 0; i++) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是任務%ld %@",i,[NSThread currentThread]);
}];
//將任務添加到隊列中
[otherQueue addOperation:op];
}
當我們將任務添加到隊列中時,不需要我們手動去開始任務,任務會自動開始
3.2隊列的最大并發數
最大并發數就是指在這個隊列里面的任務(如果是并行的隊列),最多一次可以執行任務的個數。
舉個例子:用戶上傳100張照片,并且是異步的并發執行,如果沒有設置最大并發數的話,那么這100個任務會一起執行,且會影響性能,如果我們將最大并發數設置為10的話,則這個100個任務會被分成10組,每組10個任務,10組任務間 一個一個執行。
NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init]; //?< 其它線程
//最大并發數
otherQueue.maxConcurrentOperationCount = 10;//?< 最大并發數
for (NSInteger i = 0; i < 100; i++) {
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"我是任務%ld %@",i,[NSThread currentThread]);
[otherQueue addOperation:op];
}];
3.3隊列添加任務的其它方法(Block)
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
[queue addOperationWithBlock:^{
//這里直接放任務 就可以了
NSLog(@"我是block的任務 %@",[NSThread currentThread]);
}];
4任務的依賴關系
相比GCD來說,NSOperation在設置依賴關系上要比GCD方便的多只需要很少的代碼就可以完成。假設需求: 2 , 3任務都完成后 再去完成op1;如果是GCD的話,我們可以用信號量、barrier來實現我們的效果,但是一般實現起來稍微有些麻煩,下面我們來看下NSOperation是如何來設置依賴關系的
// 任務 添加依賴關系
//創建兩個隊列
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
NSOperationQueue *otherQueue = [[NSOperationQueue alloc]init];
//創建3個任務
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"任務1 %@",[NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"任務2 %@",[NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"任務3 %@",[NSThread currentThread]);
}];
// 2 , 3任務都完成后 在完成op1
[op1 addDependency:op2];
[op1 addDependency:op3];
[otherQueue addOperation:op3];
[mainQueue addOperation:op2];
[otherQueue addOperation:op1];
//不受隊列的影響 隨意依賴
其中addDependency就是設置依賴關系的方法,只要一句就夠了,值得注意的是,所謂的依賴關系指的是任務之間的關系,而不是隊列的關系。