標籤:des blog os io 使用 ar strong for 檔案
NSOperation的作用配合使用NSOperation和NSOperationQueue也能實現多線程編程1、NSOperation和NSOperationQueue實現多線程的具體步驟2、先將需要執行的操作封裝到一個NSOperation對象中3、然後將NSOperation對象添加到NSOperationQueue中4、系統會自動將NSOperationQueue中的NSOperation取出來5、將取出的NSOperation封裝的操作放到一條新線程中執行NSOperation是個抽象類別,並不具備封裝操作的能力,必須使用它的子類1、使用NSOperation子類的方式有3種2、NSInvocationOperation3、NSBlockOperation4、自訂子類繼承NSOperation,實現內部相應的方法下面是DEMO@interface CZViewController ()/** NSOperation操作隊列 */@property (nonatomic, strong) NSOperationQueue *queue;@end@implementation CZViewController// 將操作添加到隊列即可- (NSOperationQueue *)queue{ if (!_queue) _queue = [[NSOperationQueue alloc] init]; return _queue;}- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ [self opDemo6];}/** 暫停操作 */- (IBAction)pause{ // 1. 判斷隊列中是否有操作 if (self.queue.operationCount == 0) { NSLog(@"沒有操作"); return; } // 2. 如果沒有被掛起(正在執行),才需要暫停 // 只會掛起當前隊列中還沒有被調度(沒有被安排到線程上工作的操作)才會被掛起 if (!self.queue.isSuspended) { NSLog(@"暫停"); [self.queue setSuspended:YES]; } else { NSLog(@"已經暫停"); }}/** 繼續操作 */- (IBAction)resume{ // 1. 判斷隊列中是否有操作 if (self.queue.operationCount == 0) { NSLog(@"沒有操作"); return; } // 2. 如果有被擱置動作,才需要繼續(恢複) if (self.queue.isSuspended) { NSLog(@"繼續"); [self.queue setSuspended:NO]; } else { NSLog(@"正在執行"); }}#pragma mark - NSOperation演練/** 操作之間的依賴 */- (void)opDemo6{ NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"正在下載圖書 。。。 %@", [NSThread currentThread]); }]; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"正在解壓縮圖書 。。。 %@", [NSThread currentThread]); }]; NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"正在儲存到磁碟 。。。 %@", [NSThread currentThread]); }]; NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"更新書架(UI),提示使用者可以閱讀 。。。 %@", [NSThread currentThread]); }]; // 指定操作之間的”依賴“關係,某一個操作的執行,必須等待另一個操作完成才會開始 // 依賴關係是可以跨隊列指定的 [op2 addDependency:op1]; [op3 addDependency:op2]; [op4 addDependency:op3]; // *** 添加依賴的時候,注意不要出現循環相依性// [op3 addDependency:op4]; [self.queue addOperation:op1]; [self.queue addOperation:op2]; [self.queue addOperation:op3]; // 主隊列更新UI [[NSOperationQueue mainQueue] addOperation:op4];}/** 最大並發數 */- (void)opDemo5{ // 設定隊列的最大並發數,隊列是負責調度操作的 /** 最大並發數的應用情境: 1> 使用者在使用3G的時候 限制線程的數量,省電,省流量(省錢) 2> 使用者使用WIFI的時候(區域網路) 增加線程數量,提高使用者的體驗 maxConcurrentOperationCount 如果== 1,類似於串列隊列非同步方法呼叫 */ self.queue.maxConcurrentOperationCount = 1; for (int i = 0; i < 10; i++) { [self.queue addOperationWithBlock:^{ // 類比休眠 [NSThread sleepForTimeInterval:1.0f]; NSLog(@"正在下載 %@ %d", [NSThread currentThread], i); }]; }}/** Block操作,添加執行塊 */- (void)opDemo4{ // 執行個體化block操作 NSBlockOperation *op = [[NSBlockOperation alloc] init]; // 設定最大並發(操作)數,不會限制執行塊! self.queue.maxConcurrentOperationCount = 2; // 添加執行塊 [op addExecutionBlock:^{ NSLog(@"下載書籍1 %@", [NSThread currentThread]); }]; // 繼續添加塊 [op addExecutionBlock:^{ NSLog(@"下載書籍2 %@", [NSThread currentThread]); }]; // 繼續添加塊 [op addExecutionBlock:^{ NSLog(@"下載書籍3 %@", [NSThread currentThread]); }]; // 繼續添加塊 [op addExecutionBlock:^{ NSLog(@"下載書籍4 %@", [NSThread currentThread]); }]; // 繼續添加塊 [op addExecutionBlock:^{ NSLog(@"下載書籍5 %@", [NSThread currentThread]); }]; // 啟動操作,在主線程執行 // 如果執行塊的數量超過1,就會自動進入其他線程執行(非同步) // 具體開啟線程的數量,由系統決定 // 執行塊的調度與操作的調度非常像// [op start]; [self.queue addOperation:op];}/** 直接添加塊操作 */- (void)opDemo3{ // 只要將操作添加到隊列就會立即被調度(執行) for (int i = 0; i < 10; i++) { [self.queue addOperationWithBlock:^{ NSLog(@"下載開始 %@ - %@", [NSThread currentThread], @(i)); }]; } // 向主隊列中添加操作 [[NSOperationQueue mainQueue] addOperationWithBlock:^{ NSLog(@"下載開始 %@ - %@", [NSThread currentThread], nil); }];}/** NSBlockOperation */- (void)opDemo2{ for (int i = 0; i < 10; i++) { // 指定一個塊操作 NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"下載開始 %@ - %@", [NSThread currentThread], @(i)); }]; // 將塊操作添加到隊列 [self.queue addOperation:op1]; }}#pragma mark Invocation的調度方法- (void)download:(id)obj{ NSLog(@"下載開始 %@ - %@", [NSThread currentThread], obj);}/** NSInvocationOperation */- (void)opDemo1{ for (int i = 0; i < 10; i++) { NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(download:) object:@(i)]; // 如果直接啟動,會在主線程執行 // [op1 start]; // 添加到隊列,就會建立線程,非同步執行 [self.queue addOperation:op1]; }}@end//標頭檔@interface NSOperation : NSObject {- (id)init; // designated initializer//開始任務- (void)start;- (void)main;//任務是否取消- (BOOL)isCancelled;- (void)cancel;//是否正在執行- (BOOL)isExecuting;//是否完成執行- (BOOL)isFinished;- (BOOL)isConcurrent;- (BOOL)isReady;//隊列之間的依賴操作使用的方法- (void)addDependency:(NSOperation *)op;- (void)removeDependency:(NSOperation *)op;//隊列組依賴- (NSArray *)dependencies;//隊列優先順序- (NSOperationQueuePriority)queuePriority;- (void)setQueuePriority:(NSOperationQueuePriority)p;#if NS_BLOCKS_AVAILABLE- (void (^)(void))completionBlock NS_AVAILABLE(10_6, 4_0);- (void)setCompletionBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);#endif//等待直到完成- (void)waitUntilFinished NS_AVAILABLE(10_6, 4_0);- (double)threadPriority NS_AVAILABLE(10_6, 4_0);- (void)setThreadPriority:(double)p NS_AVAILABLE(10_6, 4_0);@endNS_CLASS_AVAILABLE(10_6, 4_0)@interface NSBlockOperation : NSOperation {@private id _private2; void *_reserved2;}#if NS_BLOCKS_AVAILABLE+ (id)blockOperationWithBlock:(void (^)(void))block;- (void)addExecutionBlock:(void (^)(void))block;- (NSArray *)executionBlocks;#endif@end- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;- (id)initWithInvocation:(NSInvocation *)inv;// designated initializer- (NSInvocation *)invocation;- (id)result;@endFOUNDATION_EXPORT NSString * const NSInvocationOperationVoidResultException NS_AVAILABLE(10_5, 2_0);FOUNDATION_EXPORT NSString * const NSInvocationOperationCancelledException NS_AVAILABLE(10_5, 2_0);N- (void)addOperation:(NSOperation *)op;- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait NS_AVAILABLE(10_6, 4_0);#if NS_BLOCKS_AVAILABLE- (void)addOperationWithBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);#endif//隊列組- (NSArray *)operations;- (NSUInteger)operationCount NS_AVAILABLE(10_6, 4_0);//最大並發數- (NSInteger)maxConcurrentOperationCount;- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;enum { NSOperationQueueDefaultMaxConcurrentOperationCount = -1};//設定暫停- (void)setSuspended:(BOOL)b;- (BOOL)isSuspended;//設定名字- (void)setName:(NSString *)n NS_AVAILABLE(10_6, 4_0);- (NSString *)name NS_AVAILABLE(10_6, 4_0);//取消所有人去- (void)cancelAllOperations;//等待所有任務完成- (void)waitUntilAllOperationsAreFinished;//當前隊列+ (id)currentQueue NS_AVAILABLE(10_6, 4_0);//主隊列+ (id)mainQueue NS_AVAILABLE(10_6, 4_0);@end
ios多線程之NSOperation和NSOperationQueue