NSOperation&&NSOperationQueue
簡介
NSOperation袱讹、NSOperationQueue 是蘋果提供給我們的一套多線程解決方案。實際上 NSOperation席镀、NSOperationQueue 是基于 GCD 更高一層的封裝,完全面向?qū)ο蟆5潜?GCD 更簡單易用、代碼可讀性也更高颊咬。
NSOperation&NSOperationQueue--操作和操作隊列
既然是基于 GCD 的更高一層的封裝。那么牡辽,GCD 中的一些概念同樣適用于 NSOperation、NSOperationQueue敞临。在 NSOperation态辛、NSOperationQueue 中也有類似的任務(wù)(操作)和隊列(操作隊列)的概念。
-
操作(Operation):
要執(zhí)行的任務(wù)挺尿,GCD中放在Block中的任務(wù)
在NSOperation中奏黑,我們使用我們使用NSOperation子類NSInvocationOperation、NSBlockOperation或者自定義子類來封裝操作编矾。
-
操作隊列(NSOperationQueue):
操作隊列即用來存放操作的隊列熟史。不同于GCD中的調(diào)度隊列FIFO(先進先出)的原則
操作隊列通過設(shè)置最大并發(fā)操作數(shù)
maxConcurrentOperationCount
來控制同一時間執(zhí)行任務(wù)的數(shù)量,從而達到控制并發(fā)窄俏、串行蹂匹,并不是來控制線程的多少,當并發(fā)數(shù)為1的時候就是順序執(zhí)行,大于1的時候并發(fā)執(zhí)行凹蜈,順序不確定(默認并發(fā)數(shù)-1限寞,沒有并發(fā)限制)NSOperationQueue為我們提供了2種不同類型的隊列:主隊列和自定義隊列。主隊列運行在主線程之上仰坦,自定義隊列在后臺執(zhí)行履植。
NSOperation&&NSOperationQueue實現(xiàn)多線程步驟:
1.創(chuàng)建任務(wù):先將需要執(zhí)行的操作封裝到NSOperation對象中。
2.創(chuàng)建隊列:創(chuàng)建NSOperationQueue悄晃。
3.添加任務(wù)到隊列中:將NSOperation對象添加到NSOperationQueue中玫霎。
NSOperation三種創(chuàng)建方式
NSOperation是個抽象類,實際運用時中需要使用它的子類妈橄,有三種方式:
1.使用子類NSInvocationOperation
2.使用子類NSBlockOperation
3.定義繼承自NSOperation的子類
- 子類NSInvocationOperation(很少使用)
//創(chuàng)建操作
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(Task:) object:nil];
//start方法開始執(zhí)行操作(同步操作沒有開啟線程)
[invocationOperation start];
-(void)Task:(id)objec{
NSLog(@"operaton:%@",[NSThread currentThread]);
}
//創(chuàng)建隊列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
//創(chuàng)建操作
NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(Task:) object:nil];
//將操作添加到隊列中自動異步執(zhí)行局(新線程)
[operationQueue addOperation:invocationOperation];
-(void)Task:(id)objec{
NSLog(@"operaton:%@",[NSThread currentThread]);
}
總結(jié):
單獨使用NSOperationQueue執(zhí)行任務(wù)是同步執(zhí)行任務(wù)的(沒有開啟新的線程)庶近,將操作添加到操作隊列中自動異步執(zhí)行
- 子類NSBlockOperation
1.Block初始化操作
NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"TaskA:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskB:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskC:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskD:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskE:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskF:%@",[NSThread currentThread]);
}];
[blockOperation start];
2.alloc初始化操作
NSBlockOperation *blockOperation = [[NSBlockOperation alloc]init];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskB:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskC:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskD:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskE:%@",[NSThread currentThread]);
}];
[blockOperation addExecutionBlock:^{
NSLog(@"TaskF:%@",[NSThread currentThread]);
}];
[blockOperation start];
3.操作添加到操作隊列中執(zhí)行
//創(chuàng)建任務(wù)
NSBlockOperation *blockOperationA = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"TaskA:%@",[NSThread currentThread]);
}];
NSBlockOperation *blockOperationB = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"TaskB:%@",[NSThread currentThread]);
}];
NSBlockOperation *blockOperationC = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"TaskC:%@",[NSThread currentThread]);
}];
NSBlockOperation *blockOperationD = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"TaskD:%@",[NSThread currentThread]);
}];
//添加隊列
NSOperationQueue *operationQueue = [[NSOperationQueue alloc]init];
[operationQueue addOperation:blockOperationA];
[operationQueue addOperation:blockOperationB];
[operationQueue addOperation:blockOperationC];
[operationQueue addOperation:blockOperationD];
[operationQueue addOperationWithBlock:^{
NSLog(@"TaskE:%@",[NSThread currentThread]);
}];
總結(jié):
1.非操作隊列管理:
無論是blockOperationWithBlock初始化的操作還是[[NSBlockOperation alloc]init]初始化的操作,當操作任務(wù)數(shù)量為1的時候同步執(zhí)行眷细,當前線程執(zhí)行任務(wù)拦盹,當操作/任務(wù)數(shù)量大于1的時候,所有的任務(wù)溪椎,包括初始化第一個block任務(wù)普舆,都可以異步執(zhí)行恬口。(可以異步執(zhí)行不是一定異步執(zhí)行,每個任務(wù)任務(wù)都有可能在當前線程或者新線程執(zhí)行沼侣,具體由系統(tǒng)決定)
2.操作隊列管理:
操作添加到隊列后自動異步執(zhí)行祖能,開啟新線程
- 自定義NSOperation子類
NSOperationQueue操作隊列
- 操作隊列類型
NSOperationQueue 一共有兩種隊列:主隊列、自定義隊列蛾洛。其中自定義隊列同時包含了串行养铸、并發(fā)功能。
//主隊列
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
//自定義隊列
NSOperationQueue *concurrentQueue = [[NSOperationQueue alloc]init];
- 操作隊列添加任務(wù)
- (void)addOperation:(NSOperation *)operation;
- 操作依賴
NSOperation之間可以通過設(shè)置依賴來管理任務(wù)的執(zhí)行順序(不能相互依賴轧膘,比如A依賴B钞螟,B依賴A)
[blockOperationB addDependency:blockOperationA];
- 操作隊列控制任務(wù)串行并發(fā)
1.
主隊列任務(wù)串行執(zhí)行
2.
自定義隊列通過控制最大任務(wù)并發(fā)數(shù)來控制任務(wù)串行并發(fā),maxConcurrentOperationCount
=1串行執(zhí)行谎碍,maxConcurrentOperationCount
大于1鳞滨,或者默認值,并發(fā)執(zhí)行
NSOperation與GCD對比
- GCD是純C語言的API蟆淀,NSOperationQueue是基于GCD的OC版本封裝拯啦,GCD執(zhí)行效率更高
- GCD只支持FIFO的隊列,NSOperationQueue可以很方便地調(diào)整執(zhí)行順序熔任、設(shè)置最大并發(fā)數(shù)量
- 依賴關(guān)系:NSOperationQueue可以在輕松在Operation間設(shè)置依賴關(guān)系褒链,而GCD需要寫很多的代碼才能實現(xiàn)(dispatch_barrier_async來實現(xiàn))
- KVO:NSOperationQueue支持KVO,可以監(jiān)測operation是否正在執(zhí)行(isExecuted)疑苔、是否結(jié)束(isFinished)甫匹,是否取消(isCanceld)
操作&&操作隊列多線程總結(jié):
-
隊列中操作的執(zhí)行順序:
添加到隊列中的操作執(zhí)行順序由maxConcurrentOperationCount
最大操作并發(fā)數(shù)決定,同時受操作依賴影響 -
隊列中操作開啟線程情況:
添加到隊列中的操作開啟了新線程執(zhí)行(具體數(shù)量系統(tǒng)決定)