一哥攘、簡介
NSOperation是蘋果提供給我們的一套多線程解決方案涕俗。實際上NSOperation是基于GCD更高一層的封裝,但是比GCD更簡單易用聪黎、代碼可讀性也更高。
NSOperation需要配合NSOperationQueue來實現(xiàn)多線程妨马。因為默認情況下挺举,NSOperation單獨使用時系統(tǒng)同步執(zhí)行操作杀赢,并沒有開辟新線程的能力烘跺,只有配合NSOperationQueue才能實現(xiàn)異步執(zhí)行。
NSOperation實現(xiàn)多線程的使用步驟分為三步:
- 創(chuàng)建任務(wù):先將需要執(zhí)行的操作封裝到一個NSOperation對象中脂崔。
- 創(chuàng)建隊列:創(chuàng)建NSOperationQueue對象滤淳。
- 將任務(wù)加入到隊列中:然后將NSOperation對象添加到NSOperationQueue中。
二砌左、使用
1脖咐、創(chuàng)建任務(wù)
NSOperation是個抽象類,并不能封裝任務(wù)汇歹。我們只有使用它的子類來封裝任務(wù)屁擅。我們有三種方式來封裝任務(wù)。
使用子類NSInvocationOperation
使用子類NSBlockOperation
定義繼承自NSOperation的子類产弹,通過實現(xiàn)內(nèi)部相應(yīng)的方法來封裝任務(wù)派歌。
在不使用NSOperationQueue,單獨使用NSOperation的情況下系統(tǒng)同步執(zhí)行操作痰哨,下面我們學習以下任務(wù)的三種創(chuàng)建方式胶果。
//1.使用子類NSInvocationOperation
- (void)NSInvocationOperationUse{
//在沒有使用NSOperationQueue、單獨使用NSInvocationOperation的情況下斤斧,NSInvocationOperation在主線程執(zhí)行操作早抠,并沒有開啟新線程。
//1.創(chuàng)建NSInvocationOperation對象
NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:(@selector(runOp)) object:nil];
//2.開始執(zhí)行操作
[op start];
}
- (void)runOp{
NSLog(@"runOp------%@",[NSThread currentThread]);
}
//2.使用子類NSBlockOperationUse
- (void)NSBlockOperationUse{
//NSBlockOperation提供了一個方法addExecutionBlock:撬讽,通過addExecutionBlock:就可以為NSBlockOperation添加額外的操作蕊连,這些額外的操作就會在其他線程并發(fā)執(zhí)行悬垃。
//1.創(chuàng)建NSBlockOperation對象
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
//主線程
NSLog(@"NSBlockOperationUse------%@",[NSThread currentThread]);
}];
// 添加額外的任務(wù)(在子線程執(zhí)行)
[op addExecutionBlock:^{
NSLog(@"2------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"3------%@", [NSThread currentThread]);
}];
[op addExecutionBlock:^{
NSLog(@"4------%@", [NSThread currentThread]);
}];
//2.開始執(zhí)行操作
[op start];
}
//3.定義繼承自NSOperation的子類
- (void)NSOperationUse{
//主線程
ZQNSOperation *op = [[ZQNSOperation alloc]init];
[op start];
}
//ZQNSOperation.h
#import <Foundation/Foundation.h>
@interface ZQNSOperation : NSOperation
@end
//ZQNSOperation.m 重新main方法
#import "ZQNSOperation.h"
@implementation ZQNSOperation
- (void)main{
//任務(wù)
for (int i = 0; i < 2; ++i) {
NSLog(@"1-----%@",[NSThread currentThread]);
}
}
@end
2.創(chuàng)建隊列
和GCD中的并發(fā)隊列、串行隊列略有不同的是:NSOperationQueue一共有兩種隊列:主隊列咪奖、其他隊列盗忱。其中其他隊列同時包含了串行、并發(fā)功能羊赵。下邊是主隊列趟佃、其他隊列的基本創(chuàng)建方法和特點。
主隊列
凡是添加到主隊列中的任務(wù)(NSOperation)昧捷,都會放到主線程中執(zhí)行
NSOperationQueue *queue = [NSOperationQueue mainQueue];
其他隊列(非主隊列)
添加到這種隊列中的任務(wù)(NSOperation)闲昭,就會自動放到子線程中執(zhí)行
同時包含了:串行、并發(fā)功能
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
3.將任務(wù)添加到隊列
- (void)NSInvocationOperationUse{
//1.創(chuàng)建NSInvocationOperation對象
NSInvocationOperation *op = [[NSInvocationOperation alloc]initWithTarget:self selector:(@selector(runOp)) object:nil];
//2.創(chuàng)建NSBlockOperation
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
for (int i = 0; i < 2; ++i) {
NSLog(@"1-----%@", [NSThread currentThread]);
}
}];
//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//2.開始執(zhí)行操作
[queue addOperation:op];
[queue addOperation:op2];
}
- (void)runOp{
NSLog(@"runOp------%@",[NSThread currentThread]);
}
可以直接在block中添加任務(wù)靡挥,無需先創(chuàng)建
//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//添加操作到隊列中
[queue addOperationWithBlock:^{
for (int i = 0; i < 2; ++i) {
NSLog(@"-----%@", [NSThread currentThread]);
}
}];
4.串行 并行
最大并發(fā)數(shù):maxConcurrentOperationCount
maxConcurrentOperationCount默認情況下為-1序矩,表示不進行限制,默認為并發(fā)執(zhí)行跋破。
當maxConcurrentOperationCount為1時簸淀,進行串行執(zhí)行,開啟1條子線程毒返。
當maxConcurrentOperationCount大于1時租幕,進行并發(fā)執(zhí)行,當然這個值不應(yīng)超過系統(tǒng)限制拧簸,即使自己設(shè)置一個很大的值劲绪,系統(tǒng)也會自動調(diào)整。
maxConcurrentOperationCount為0盆赤,不執(zhí)行隊列任務(wù)贾富。
//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//設(shè)置maxConcurrentOperationCount
queue.maxConcurrentOperationCount = 2;
//添加任務(wù)
[queue addOperationWithBlock:^{
NSLog(@"1-----%@", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"2-----%@", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"3-----%@", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"4-----%@", [NSThread currentThread]);
}];
[queue addOperationWithBlock:^{
NSLog(@"5-----%@", [NSThread currentThread]);
}];
5.操作依賴
比如說有A、B兩個操作牺六,其中A執(zhí)行完操作颤枪,B才能執(zhí)行操作,那么就需要讓B依賴于A淑际。
//創(chuàng)建隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"1-----%@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"2-----%@", [NSThread currentThread]);
}];
[op2 addDependency:op1]; //添加依賴關(guān)系畏纲,op2依賴于op1
[queue addOperation:op1];
[queue addOperation:op2];