參考鏈接:http://www.cocoachina.com/ios/20151201/14517.html
- NSOperationQueue本身由Grand Central Dispatch隊(duì)列支持
- 由于NSOperation的許多好處來(lái)自NSOperationQueue,因此幾乎總是優(yōu)先將操作添加到隊(duì)列而不是直接調(diào)用start。
- 依賴關(guān)系是 operation 自身的狀態(tài),也就是說(shuō)有依賴關(guān)系的 operations 可以處在不同的 NSOperationQueue 中。
NSInvocationOperation
在其他線程中單獨(dú)使用子類 NSInvocationOperation,操作是在當(dāng)前調(diào)用的其他線程執(zhí)行的,并沒(méi)有開啟新線程。
- (void)operationTest {
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(NSInvocationOperationAction:) object:@"haha"];
[op start];
}
- (void)NSInvocationOperationAction:(NSString *)str {
NSLog(@"test result = %@",str);
}
NSBlockOperation
使用子類 NSBlockOperation,并調(diào)用方法 AddExecutionBlock: 的情況下,blockOperationWithBlock:方法中的操作 和 addExecutionBlock: 中的操作是在不同的線程中異步執(zhí)行的。而且,這次執(zhí)行結(jié)果中 blockOperationWithBlock:方法中的操作也不是在當(dāng)前線程(主線程)中執(zhí)行的。從而印證了blockOperationWithBlock: 中的操作也可能會(huì)在其他線程(非當(dāng)前線程)中執(zhí)行。
一般情況下,如果一個(gè) NSBlockOperation 對(duì)象封裝了多個(gè)操作。NSBlockOperation 是否開啟新線程,取決于操作的個(gè)數(shù)。如果添加的操作的個(gè)數(shù)多,就會(huì)自動(dòng)開啟新線程。當(dāng)然開啟的線程數(shù)是由系統(tǒng)來(lái)決定的。
- (void)operationTest {
NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"test result = block operation");
NSLog(@"block 線程:%@",[NSThread currentThread]);
}];
[block addExecutionBlock:^{
NSLog(@"addExecutionBlock 開啟新線程:%@",[NSThread currentThread]);
}];
[block start];
}
NSOperationQueue
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(NSInvocationOperationAction:) object:@"queue haha"];
NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"test queue result = block operation");
NSLog(@"開啟新線程:%@",[NSThread currentThread]);
}];
[block addExecutionBlock:^{
NSLog(@"開啟新線程:%@",[NSThread currentThread]);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:op];
[queue addOperation:block];
[queue addOperationWithBlock:^{
NSLog(@"test queue add block");
NSLog(@"開啟新線程:%@",[NSThread currentThread]);
}];
最大并發(fā)操作數(shù):maxConcurrentOperationCount
- maxConcurrentOperationCount 默認(rèn)情況下為-1,表示不進(jìn)行限制,可進(jìn)行并發(fā)執(zhí)行。
- maxConcurrentOperationCount 為1時(shí),隊(duì)列為串行隊(duì)列。只能串行執(zhí)行。
- maxConcurrentOperationCount 大于1時(shí),隊(duì)列為并發(fā)隊(duì)列。操作并發(fā)執(zhí)行,當(dāng)然這個(gè)值不應(yīng)超過(guò)系統(tǒng)限制,即使自己設(shè)置一個(gè)很大的值,系統(tǒng)也會(huì)自動(dòng)調(diào)整為 min{自己設(shè)定的值,系統(tǒng)設(shè)定的默認(rèn)最大值}。
NSOperation 操作依賴
- - (void)addDependency:(NSOperation *)op; 添加依賴,使當(dāng)前操作依賴于操作 op 的完成。
- - (void)removeDependency:(NSOperation *)op; 移除依賴,取消當(dāng)前操作對(duì)操作 op 的依賴。
- @property (readonly, copy) NSArray<NSOperation *> *dependencies; 在當(dāng)前操作開始執(zhí)行之前完成執(zhí)行的所有操作對(duì)象數(shù)組。
NSOperation 優(yōu)先級(jí)
NSOperation 提供了queuePriority(優(yōu)先級(jí))屬性,queuePriority屬性適用于同一操作隊(duì)列中的操作,不適用于不同操作隊(duì)列中的操作。默認(rèn)情況下,所有新創(chuàng)建的操作對(duì)象優(yōu)先級(jí)都是NSOperationQueuePriorityNormal。但是我們可以通過(guò)setQueuePriority:方法來(lái)改變當(dāng)前操作在同一隊(duì)列中的執(zhí)行優(yōu)先級(jí)。
// 優(yōu)先級(jí)的取值
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {
NSOperationQueuePriorityVeryLow = -8L,
NSOperationQueuePriorityLow = -4L,
NSOperationQueuePriorityNormal = 0,
NSOperationQueuePriorityHigh = 4,
NSOperationQueuePriorityVeryHigh = 8
};
queuePriority 屬性決定了進(jìn)入準(zhǔn)備就緒狀態(tài)下的操作之間的開始執(zhí)行順序。并且,優(yōu)先級(jí)不能取代依賴關(guān)系。有依賴關(guān)系的,等依賴執(zhí)行完之后才進(jìn)入就緒狀態(tài)
自定義繼承自 NSOperation 的子類
非并發(fā)操作
一般只覆寫main方法
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface TestOperation : NSOperation
@end
NS_ASSUME_NONNULL_END
@implementation TestOperation
- (void)main {
if (!self.isCancelled) {
for (int i = 0; i < 2; i++) {
[NSThread sleepForTimeInterval:2];
NSLog(@"1---%@", [NSThread currentThread]);
}
}
}
@end
并發(fā)操作
實(shí)現(xiàn)并發(fā)操作要點(diǎn):
- 重寫isConcurrent函數(shù), 返回YES, 這個(gè)告訴系統(tǒng)各單位注意了我這個(gè)operation是要并發(fā)的.
- 重寫start()函數(shù).
- 重寫isExecuting和isFinished函數(shù)
為什么在并發(fā)情況下需要自己來(lái)設(shè)定isExecuting和isFinished這兩個(gè)狀態(tài)量呢? 因?yàn)樵诓l(fā)情況下系統(tǒng)不知道operation什么時(shí)候finished, operation里面的task一般來(lái)說(shuō)是異步執(zhí)行的, 也就是start函數(shù)返回了operation不一定就是finish了, 這個(gè)你自己來(lái)控制, 你什么時(shí)候?qū)sFinished置為YES(發(fā)送相應(yīng)的KVO消息), operation就什么時(shí)候完成了.