iOS多線程之NSOperation
在GCD的基礎上包裝而來,相較于GCD而言,可控性更強,并且加入了操作依賴。
NSOperation是一個抽象的基類,不可直接使用,隻能使用其子類,為子類提供了線程的建立狀态,優先級,依賴和取消等操作。系統已經給我們封裝了NSBlockOperation和NSInvocationOperation這兩個實體類,供我們使用,當然我們也可以自定義NSOperation的子類,需要重載-(void)main這個方法。
NSOperation可以自己獨立執行(直接調用[operation start]), 也可以放到NSOperationQueue裡面執行。NSOperation 在預設情況下是非并發的,當你将此操作放到線程執行,他會阻塞該線程,直到執行完成。NSOperation也可以直接實作并發執行。但需要重寫isConcurrent isExecuting isFinished 以及start函數,讓isConcurrent 傳回YES,再開始結束的時候手動設定 isExecuting isFinished的狀态;如果将NSOperation加入NSOperationQueue隊列中去執行,那麼我們隻需去管理NSOperationQueue隊列即可,它基本上是并發執行。下面先了解系統提供給我們的NSOperation NSBlockOperation NSInvocationOperation NSOperationQueue的一些屬性與方法。
NSOperation方法屬性
- (void)start;//開始執行操作
- (void)main;//操作入口函數
@property (readonly, getter=isCancelled) BOOL cancelled;//操作狀态,表示操作是否取消
- (void)cancel;//取消操作,将cancelled狀态置成YES,而非取消操作
@property (readonly, getter=isExecuting) BOOL executing;//操作狀态,表示操作是否正在執行
@property (readonly, getter=isFinished) BOOL finished;//操作狀态,表示操作是否結束
@property (readonly, getter=isConcurrent) BOOL concurrent; // 判斷操作是否并行
@property (readonly, getter=isAsynchronous) BOOL asynchronous ;// 判斷操作是否異步
@property (readonly, getter=isReady) BOOL ready;// 判斷操作準備完成
- (void)addDependency:(NSOperation *)op;//添加依賴操作
- (void)removeDependency:(NSOperation *)op;//移除依賴操作
@property (readonly, copy) NSArray<NSOperation *> *dependencies;//操作依賴組
typedef NS_ENUM(NSInteger, NSOperationQueuePriority) {//操作隊列優先級
NSOperationQueuePriorityVeryLow = -8L,//低
NSOperationQueuePriorityLow = -4L,//較低
NSOperationQueuePriorityNormal = 0,//正常
NSOperationQueuePriorityHigh = 4,//較高
NSOperationQueuePriorityVeryHigh = 8//高
};
@property NSOperationQueuePriority queuePriority;//操作隊列優先級
@property (nullable, copy) void (^completionBlock)(void) ;//操作完成後執行函數
- (void)waitUntilFinished ;//操作對象等待知道某個任務結束
@property double threadPriority ;//線程優先級
@property NSQualityOfService qualityOfService ;//操作對象優先級
@property (nullable, copy) NSString *name ;//操作對象名稱
+ (instancetype)blockOperationWithBlock:(void (^)(void))block;//初始化操作對象
- (void)addExecutionBlock:(void (^)(void))block;//添加操作任務
@property (readonly, copy) NSArray<void (^)(void)> *executionBlocks;//執行的任務集數組
- (nullable instancetype)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;//初始化操作對象,封裝要執行的任務
- (instancetype)initWithInvocation:(NSInvocation *)inv ;初始化操作對象,封裝要執行的任務
@property (readonly, retain) NSInvocation *invocation;//要執行的任務
@property (nullable, readonly, retain) id result;//操作結果
static const NSInteger NSOperationQueueDefaultMaxConcurrentOperationCount = -1;//操作隊列預設最大并行操作數
- (void)addOperation:(NSOperation *)op;//給操作隊列添加操作
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait ;//給操作隊列添加操作
- (void)addOperationWithBlock:(void (^)(void))block;//給操作隊列以塊的形式添加操作
@property (readonly, copy) NSArray<__kindof NSOperation *> *operations;//操作隊列操作集(所有操作)
@property (readonly) NSUInteger operationCount;//操作隊列操作個數(所有操作總數目)
@property NSInteger maxConcurrentOperationCount;//操作隊列并發執行操作個數最大個數,如果設為1,那麼就成了串行操作了。
@property (getter=isSuspended) BOOL suspended;//操作隊列是否挂起
@property (nullable, copy) NSString *name;//操作隊列名稱
@property NSQualityOfService qualityOfService;//操作隊列優先級
@property (nullable, assign ) dispatch_queue_t underlyingQueue;//潛在的隊列
- (void)cancelAllOperations;//取消操作隊列中的所有操作
- (void)waitUntilAllOperationsAreFinished;//等待直到所有操作完成
NSOperation多線程示例
-( void )initMultiOperation
{
NSInvocationOperation *myInvocationOpt=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(myFunc:) object:@"invocation"];
[myInvocationOpt setName:@"InvocationOperation"];
[myInvocationOpt start];
NSBlockOperation *myBlockOpt = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"task:%@",[NSThread currentThread]);
}];
[myInvocationOpt setName:@"BlockOperation"];
[myOpt addExecutionBlock:^{
NSLog(@"block:%@",[NSThread currentThread].name);
}];
[myOpt addExecutionBlock:^{
NSLog(@"task-block:%@",[NSThread currentThread]);
}];
[myBlockOpt start];
myOperation *myOpt=[[myOperation alloc]init];//自定義NSOperation子類,重寫main函數,當調用start函數後,自動開始從入口函數main執行操作
[myOpt setName:@"myOperation"];
[myOpt start];
}
-(void)myFunc:(NSString *)str
{
NSLog(@"task-invocation:%@----------%@",[NSThread currentThread],str);
}
NSOperationQueue隊列多線程示例
-(void)operationQueue
{
NSOperationQueue *myOptQueue=[[NSOperationQueue alloc]init];
[myOptQueue setName:@"hello"];
[myOptQueue setMaxConcurrentOperationCount:3];
NSBlockOperation *myBlock=[NSBlockOperation blockOperationWithBlock:^{
NSLog(@"My First Task");
}];
[myBlock addExecutionBlock:^{
NSLog(@"My Sencond Task");
}];
[myBlock addExecutionBlock:^{
NSLog(@"My Third Task");
}];
NSInvocationOperation *myInvocation=[[NSInvocationOperation alloc]initWithTarget:self selector:@selector(myFunc:) :@"NSInvocationOperation"];
[myInvocation setQueuePriority:NSOperationQueuePriorityVeryLow];//設定優先級
[myBlock addDependency:myInvocation];//添加依賴,myBlock執行與myInvocation之後
[myOptQueue addOperation:myInvocation];//給操作隊列添加myInvocation操作
//[myInvocation cancel];設定myInvocation操作狀态cancelled為YES,如果該操作還未執行,就取消該操作,不再執行;在執行中,等待執行完成,設定标志完成
[myOptQueue addOperation:myBlock]; //給操作隊列添加myBlock操作
[myOptQueue addOperationWithBlock:^{ //給操作隊列添加塊操作
NSLog(@"My Fourth Task");
}];
//[myOptQueue cancelAllOperations];//取消操作隊列中所有的操作
[myOptQueue setSuspended:YES];//挂起本操作隊列
if([myOptQueue isSuspended])
{
NSLog(@"setSuspended:YES");
[myOptQueue setSuspended:NO];//恢複本操作隊列
}
myInvocation.completionBlock=^{ //myInvocation操作結束後調用
NSLog(@"myInvocation over!!!");
};
}