iOS 多线程(三)NSOperation
2016-10-13 13:45
197 查看
NSOperation多线程任务类,是个“抽象类”,并不具备封装操作的能力,必须使用它的子类。
使用NSOperation子类的三种方法:
NSInvocationOperation
NSBlockOperation
自定义子类继承NSOperation,实现内部相应方法。
执行start方法,就会调用target的sel方法。
默认情况下,调用start方法并不会开启一条新线程去执行操作,而是在当前线程同步执行。
需要将NSInvocationOperation放到一个NSOperationQueue中,才会异步执行
一执行start方法,就会执行block中的代码。
添加多个任务。
1:
2 :
ZPYOperation.h
添加方式:
- (void)addOperation:(NSOperation *)op;
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait;
- (void)addOperationWithBlock:(void
(^)(void))block;
第一种方式:
第三种方式:
并发数:同时执行的任务数。比如,同时开3个线程执行3个任务,并发数就是3。
queue.maxConcurrentOperationCount=2;
输出如下:
监听操作执行完毕及添加依赖
通过设置completionBlock属性来监听操作执行完毕。
NSOperation之间可以设置依赖来保证执行顺序,
比如一定要让操作A执行完后,才能执行操作B,可以这么写
[operationB addDependency:operationA];//操作B依赖于操作A
可以在不同queue的NSOperation之间创建依赖关系,但是不能相互依赖,比如A依赖B,B依赖A
使用NSOperation子类的三种方法:
NSInvocationOperation
NSBlockOperation
自定义子类继承NSOperation,实现内部相应方法。
1 NSInVocationOperation
- (id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;执行start方法,就会调用target的sel方法。
-(void)invocationOperation{ //创建NSInvocationOperation对象 NSInvocationOperation *invocationOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(invocationRun) object:nil]; //开始执行 [invocationOperation start]; } -(void)invocationRun{ NSLog(@"invocationRun------%@",[NSThread currentThread]); }打印:
2016-10-11 19:19:43.281 NSOperation基本使用[576:407434] invoRun------<NSThread: 0x166454c0>{number = 1, name = main}由此打印可知其是在主线程中运行的。
默认情况下,调用start方法并不会开启一条新线程去执行操作,而是在当前线程同步执行。
需要将NSInvocationOperation放到一个NSOperationQueue中,才会异步执行
2 NSBlockOperation
+ (id)blockOperationWithBlock:(void (^)(void))block;一执行start方法,就会执行block中的代码。
//NSBlockOperation -(void)blockOperation{ //创建NSBlockOperation对象 NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation 1------%@",[NSThread currentThread]); }]; //开始执行 [blockOperation start]; }打印:
2016-10-11 19:32:37.946 NSOperation基本使用[579:416891] blockOperation 1------<NSThread: 0x17632dd0>{number = 1, name = main}由此可以看出其也是同步执行,并没有开启新线程。
添加多个任务。
//NSBlockOperation -(void)blockOperation{ //创建NSBlockOperation对象 NSBlockOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blockOperation 1------%@",[NSThread currentThread]); }]; // 添加额外的任务 [blockOperation addExecutionBlock:^{ NSLog(@"blockOperation 2------%@", [NSThread currentThread]); }]; [blockOperation addExecutionBlock:^{ NSLog(@"blockOperation 3------%@", [NSThread currentThread]); }]; [blockOperation addExecutionBlock:^{ NSLog(@"blockOperation 4------%@", [NSThread currentThread]); }]; //开始执行 [blockOperation start]; }打印多种情况
1:
2016-10-11 19:37:44.429 NSOperation基本使用[582:417738] blockOperation 1------<NSThread: 0x15d767b0>{number = 1, name = main} 2016-10-11 19:37:44.432 NSOperation基本使用[582:417738] blockOperation 3------<NSThread: 0x15d767b0>{number = 1, name = main} 2016-10-11 19:37:44.432 NSOperation基本使用[582:417738] blockOperation 4------<NSThread: 0x15d767b0>{number = 1, name = main} 2016-10-11 19:37:44.429 NSOperation基本使用[582:417815] blockOperation 2------<NSThread: 0x15d7a6b0>{number = 4, name = (null)}
2 :
2016-10-11 19:38:31.864 NSOperation基本使用[584:418141] blockOperation 2------<NSThread: 0x166732d0>{number = 3, name = (null)} 2016-10-11 19:38:31.865 NSOperation基本使用[584:418127] blockOperation 1------<NSThread: 0x1663f980>{number = 1, name = main} 2016-10-11 19:38:31.866 NSOperation基本使用[584:418141] blockOperation 3------<NSThread: 0x166732d0>{number = 3, name = (null)} 2016-10-11 19:38:31.867 NSOperation基本使用[584:418127] blockOperation 4------<NSThread: 0x1663f980>{number = 1, name = main}3
2016-10-11 19:39:29.995 NSOperation基本使用[586:418505] blockOperation 1------<NSThread: 0x16d10730>{number = 1, name = main} 2016-10-11 19:39:29.996 NSOperation基本使用[586:418525] blockOperation 2------<NSThread: 0x16e16c70>{number = 3, name = (null)} 2016-10-11 19:39:29.998 NSOperation基本使用[586:418505] blockOperation 3------<NSThread: 0x16d10730>{number = 1, name = main} 2016-10-11 19:39:29.998 NSOperation基本使用[586:418525] blockOperation 4------<NSThread: 0x16e16c70>{number = 3, name = (null)}由上面三种打印可知,NSBlockOperation封装的操作数> 1,任务执行线程不确定(不一定是开启新线程,也不一定是同步执行,像是随机的)。
3 自定义NSOperation子类
创建类继承NSOperation,实现main方法。ZPYOperation.h
#import <Foundation/Foundation.h> @interface ZPYOperation : NSOperation @endZPYOperation.m
@implementation ZPYOperation -(void)main{ NSLog(@"zpyoperation main---%@",[NSThread currentThread]); } @end使用方法:
ZPYOperation *zpy = [[ZPYOperation alloc] init]; [queue addOperation:zpy];
4 NSOperationQueue
NSOperation通过添加到NSOperationQueue,则会异步执行任务。添加方式:
- (void)addOperation:(NSOperation *)op;
- (void)addOperations:(NSArray<NSOperation *> *)ops waitUntilFinished:(BOOL)wait;
- (void)addOperationWithBlock:(void
(^)(void))block;
第一种方式:
// - (void)addOperation:(NSOperation *)op; -(void)operationQueue1{ //创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; NSLog(@"默认 maxcurrent:%d",[queue maxConcurrentOperationCount]);//默认为-1 //创建操作 NSInvocationOperation *inOp1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run1) object:nil]; NSInvocationOperation *inOp2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run2) object:nil]; NSBlockOperation *blOp1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blOp1------1----%@",[NSThread currentThread]); }]; NSBlockOperation *blOp2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"blOp2------1----%@",[NSThread currentThread]); }]; [blOp2 addExecutionBlock:^{ NSLog(@"blOp2------2----%@",[NSThread currentThread]); }]; [blOp2 addExecutionBlock:^{ NSLog(@"blOp2------3----%@",[NSThread currentThread]); }]; //添加任务到队列中 [queue addOperation:inOp1]; [queue addOperation:inOp2]; [queue addOperation:blOp1]; [queue addOperation:blOp2]; } -(void)run1{ NSLog(@"run1----------%@",[NSThread currentThread]); } -(void)run2{ NSLog(@"run2----------%@",[NSThread currentThread]); }打印:
2016-10-11 20:01:42.851 NSOperation基本使用[596:422242] 默认 maxcurrent:-1 2016-10-11 20:01:42.857 NSOperation基本使用[596:422312] run2----------<NSThread: 0x15d51d30>{number = 4, name = (null)} 2016-10-11 20:01:42.858 NSOperation基本使用[596:422312] blOp1------1----<NSThread: 0x15d51d30>{number = 4, name = (null)} 2016-10-11 20:01:42.858 NSOperation基本使用[596:422312] blOp2------1----<NSThread: 0x15d51d30>{number = 4, name = (null)} 2016-10-11 20:01:42.858 NSOperation基本使用[596:422312] blOp2------2----<NSThread: 0x15d51d30>{number = 4, name = (null)} 2016-10-11 20:01:42.858 NSOperation基本使用[596:422306] run1----------<NSThread: 0x15d7d720>{number = 3, name = (null)} 2016-10-11 20:01:42.858 NSOperation基本使用[596:422312] blOp2------3----<NSThread: 0x15d51d30>{number = 4, name = (null)}第二种方式,就是先将多个NSOperation对象存到一个NSArray中然后在添加到queue中而已。
第三种方式:
// - (void)addOperationWithBlock:(void (^)(void))block - (void)operationQueue2{ // 创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 添加操作到队列中 [queue addOperationWithBlock:^{ NSLog(@"addoperationWithBlock 1 --- %@", [NSThread currentThread]); }]; [queue addOperationWithBlock:^{ NSLog(@"addoperationWithBlock 2 --- %@", [NSThread currentThread]); }]; }打印:
2016-10-11 19:18:29.682 NSOperation基本使用[606:425449] addoperationWithBlock 2 --- <NSThread: 0x175944a0>{number = 4, name = (null)} 2016-10-11 19:18:29.681 NSOperation基本使用[606:425446] addoperationWithBlock 1 --- <NSThread: 0x176a9800>{number = 3, name = (null)}
5 maxConcurrentOperationCount
最大并发数并发数:同时执行的任务数。比如,同时开3个线程执行3个任务,并发数就是3。
- (void)operationQueue3{ // 创建队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 设置最大并发操作数 // queue.maxConcurrentOperationCount = 2; queue.maxConcurrentOperationCount = 1; // 就变成了串行队列 // 添加操作 [queue addOperationWithBlock:^{ NSLog(@"download1 --- %@", [NSThread currentThread]); [NSThread sleepForTimeInterval:0.01]; }]; [queue addOperationWithBlock:^{ NSLog(@"download2 --- %@", [NSThread currentThread]); [NSThread sleepForTimeInterval:0.01]; }]; [queue addOperationWithBlock:^{ NSLog(@"download3 --- %@", [NSThread currentThread]); [NSThread sleepForTimeInterval:0.01]; }]; [queue addOperationWithBlock:^{ NSLog(@"download4 --- %@", [NSThread currentThread]); [NSThread sleepForTimeInterval:0.01]; }]; [queue addOperationWithBlock:^{ NSLog(@"download5 --- %@", [NSThread currentThread]); [NSThread sleepForTimeInterval:0.01]; }]; [queue addOperationWithBlock:^{ NSLog(@"download6 --- %@", [NSThread currentThread]); [NSThread sleepForTimeInterval:0.01]; }]; }打印:
2016-10-11 19:52:38.283 NSOperation基本使用[609:429908] download1 --- <NSThread: 0x1452fc20>{number = 3, name = (null)} 2016-10-11 19:52:38.298 NSOperation基本使用[609:429908] download2 --- <NSThread: 0x1452fc20>{number = 3, name = (null)} 2016-10-11 19:52:38.312 NSOperation基本使用[609:429905] download3 --- <NSThread: 0x146225e0>{number = 4, name = (null)} 2016-10-11 19:52:38.326 NSOperation基本使用[609:429905] download4 --- <NSThread: 0x146225e0>{number = 4, name = (null)} 2016-10-11 19:52:38.340 NSOperation基本使用[609:429905] download5 --- <NSThread: 0x146225e0>{number = 4, name = (null)} 2016-10-11 19:52:38.353 NSOperation基本使用[609:429905] download6 --- <NSThread: 0x146225e0>{number = 4, name = (null)}当设置
queue.maxConcurrentOperationCount=2;
输出如下:
2016-10-11 17:08:20.085 NSOperation基本使用[613:432467] download2 --- <NSThread: 0x15d5c0b0>{number = 6, name = (null)} 2016-10-11 17:08:20.084 NSOperation基本使用[613:432416] download1 --- <NSThread: 0x15e5d990>{number = 5, name = (null)} 2016-10-11 17:08:20.098 NSOperation基本使用[613:432402] download3 --- <NSThread: 0x15d759b0>{number = 4, name = (null)} 2016-10-11 17:08:20.100 NSOperation基本使用[613:432416] download4 --- <NSThread: 0x15e5d990>{number = 5, name = (null)} 2016-10-11 17:08:20.109 NSOperation基本使用[613:432402] download5 --- <NSThread: 0x15d759b0>{number = 4, name = (null)} 2016-10-11 17:08:20.113 NSOperation基本使用[613:432416] download6 --- <NSThread: 0x15e5d990>{number = 5, name = (null)}由此可见,当设置为1时,也就变成了串行执行,按先后顺序执行。
6 其他常用方法:
//queue管理的所有NSOperation @property (readonly, copy) NSArray<__kindof NSOperation *> *operations; //queue管理的NSOperation数量 @property (readonly) NSUInteger operationCount NS_AVAILABLE(10_6, 4_0); @property NSInteger maxConcurrentOperationCount; //用来暂停和恢复队列 @property (getter=isSuspended) BOOL suspended; //队列名 @property (nullable, copy) NSString *name NS_AVAILABLE(10_6, 4_0); //取消所有的NSOperation - (void)cancelAllOperations; - (void)waitUntilAllOperationsAreFinished;
监听操作执行完毕及添加依赖
通过设置completionBlock属性来监听操作执行完毕。
NSOperation之间可以设置依赖来保证执行顺序,
比如一定要让操作A执行完后,才能执行操作B,可以这么写
[operationB addDependency:operationA];//操作B依赖于操作A
可以在不同queue的NSOperation之间创建依赖关系,但是不能相互依赖,比如A依赖B,B依赖A
-(void)dependencyOperation{ NSOperationQueue *queue = [[NSOperationQueue alloc] init]; NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"download1----%@", [NSThread currentThread]); }]; NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"download2----%@", [NSThread currentThread]); }]; NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"download3----%@", [NSThread currentThread]); }]; NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{ for (NSInteger i = 0; i<10; i++) { NSLog(@"download4----%@", [NSThread currentThread]); } }]; //监听操作执行完毕 [op4 setCompletionBlock:^{ NSLog(@"op4执行完毕---%@", [NSThread currentThread]); }]; NSBlockOperation *op5 = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"download5----%@", [NSThread currentThread]); }]; //监听操作执行完毕 op5.completionBlock = ^{ NSLog(@"op5执行完毕---%@", [NSThread currentThread]); }; // 设置依赖 [op3 addDependency:op1]; [op3 addDependency:op2]; [op3 addDependency:op4]; [queue addOperation:op1]; [queue addOperation:op2]; [queue addOperation:op3]; [queue addOperation:op4]; [queue addOperation:op5]; }打印:
2016-10-11 17:56:04.208 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.208 NSOperation基本使用[626:439625] download2----<NSThread: 0x17e9a830>{number = 5, name = (null)} 2016-10-11 17:56:04.211 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.211 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.209 NSOperation基本使用[626:439640] download5----<NSThread: 0x17e9ab20>{number = 7, name = (null)} 2016-10-11 17:56:04.211 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.211 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.211 NSOperation基本使用[626:439640] op5执行完毕---<NSThread: 0x17e9ab20>{number = 7, name = (null)} 2016-10-11 17:56:04.212 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.207 NSOperation基本使用[626:439626] download1----<NSThread: 0x17da6a60>{number = 4, name = (null)} 2016-10-11 17:56:04.212 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.213 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.213 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.213 NSOperation基本使用[626:439638] download4----<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.214 NSOperation基本使用[626:439638] op4执行完毕---<NSThread: 0x17da2b00>{number = 6, name = (null)} 2016-10-11 17:56:04.215 NSOperation基本使用[626:439625] download3----<NSThread: 0x17e9a830>{number = 5, name = (null)}
相关文章推荐
- ios多线程开发——nsoperation详解
- iOS多线程编程之NSOperation和NSOperationQueue的使用
- iOS多线程编程之NSOperation和NSOperationQueue的使用
- iOS多线程的初步研究(六)-- NSOperation
- 【OC】IOS多线程之NSoperation和GCD的比较
- IOS_1,ios多线程使用:NSThread和NSOperation异步加载图片
- iOS多线程之NSOperation和NSOperationQueue的使用
- iOS多线程编程之NSOperation和NSOperationQueue的使用
- iOS多线程编程之NSOperation和NSOperationQueue的使用
- iOS多线程编程之NSOperation和NSOperationQueue的使用
- IOS多线程编程之NSOperation和NSOperationQueue的使用
- IOS多线程之NSThread、NSOperation、NSInvocationOperation
- IOS 多线程 NSOperation
- IOS学习笔记50--多线程之NSOperation
- iOS多线程编程之NSOperation和NSOperationQueue的使用
- IOS学习笔记23—多线程之NSThread、NSOperation、NSInvocationOperation
- iOS多线程编程之NSOperation和NSOperationQueue的使用
- IOS学习笔记23—多线程之NSThread、NSOperation、NSInvocationOperation
- IOS多线程(NSOperation,NSOperationQueue)
- iOS多线程编程之NSOperation和NSOperationQueue的使用