您的位置:首页 > 移动开发 > IOS开发

iOS--多线程之NSOperation

2017-03-27 00:00 120 查看
做一下整理,与大家分享,不足之处请留言:

使用NSOperation时,需要使用其子类:子类有三种方式

1.NSInvocationOperation 2.NSBlockOperation 3.自定义子类继承NSOperation,实现内部相应的方法

NSInvocationOperation 2个初始化方法

- (id)initWithTarget:(id)target selector:(SEL)sel object:(nullable id)arg;

- (void)start;//执行操作

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];

[operation start];

注意:默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作。只有将operation放到一个NSOperationQueue中,才会异步执行操作。

NSBlockOperation

创建NSBlockOperation对象 + (id)blockOperationWithBlock:(void (^)(void))block;

通过addExecutionBlock:方法添加更多的操作 - (void)addExecutionBlock:(void (^)(void))block;

用法:

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^(){

NSLog(@"执行了一个同步操作");

}];

[operation addExecutionBlock:^() {  //异步操作 

NSLog(@"执行了第2个新的操作,线程:%@", [NSThread currentThread]); }];

[operation addExecutionBlock:^() {  //异步操作 

NSLog(@"执行了第3个新的操作,线程:%@", [NSThread currentThread]); }];

[operation start];// 开始执行任务

注意:一般情况下,如果一个NSBlockOperation对象封装了多个任务。那么除第一个任务外,其他的任务会在新线程(子线程)中执行。即,NSBlockOperation是否开启新线程取决于任务的个数,任务的个数多,会自动开启新线程。但是第一个被执行的任务是同步执行,除第一个任务外,其他任务是异步执行的。

NSOperationQueue

NSOperation可以调用start方法来执行任务,但默认是同步执行的,如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作

添加操作到NSOperationQueue中

- (void)addOperation:(NSOperation *)op;

- (void)addOperationWithBlock:(void (^)(void))block;

NSOperation的completionBlock属性

如果想在操作执行完毕之后,还希望做一些其他的事情,可以通过completionBlock实现,并且永远是等待操作所有任务执行完毕最后被调用。

同步执行

NSBlockOperation *blkop = [NSBlockOperation blockOperationWithBlock:^{

[NSThread sleepForTimeInterval:3];

NSLog(@"执行%@",[NSThread currentThread]); }];

blkop.completionBlock = ^{ NSLog(@"完成"); };

[blkop start];

异步执行

NSBlockOperation *blkop = [NSBlockOperation blockOperationWithBlock:^{

[NSThread sleepForTimeInterval:4];

NSLog(@"执行%@",[NSThread currentThread]); }];

blkop.completionBlock = ^{ NSLog(@"完成"); };

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

[queue addOperation:blkop];

//如果一个操作是被加到操作队列中,然后才设置completionBlock,这样是可以的

总结:如果操作是通过调用start方法触发的,那么completionBlock必须要在start之前设置。如果操作是通过加入操作队列被触发的,那么completionBlock可以在操作添加到操作队列之后设置,只要保证此时操作没有被执行即可。

最大并发数 同时执行的任务数

最大并发数的相关方法

- (NSInteger)maxConcurrentOperationCount;

- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

// 设置最大并发操作数 // queue.maxConcurrentOperationCount = 5;

queue.maxConcurrentOperationCount = 1; // 就变成了串行队列

NSOperation添加Dependency

操作B依赖于操作A,所以一定要等操作A执行完毕才能执行操作B。执行顺序,不取决于添加到队列的先后顺序,而是取决于依赖关系(注:maxConcurrentOperationCount = 1除外,因为maxConcurrentOperationCount = 1时,操作队列为串行队列,如果没有给操作添加依赖,此时操作的执行顺序取决于操作添加到队列中的先后顺序。即便如此,maxConcurrentOperationCount = 1时,队列中的操作也并不一定在同一个线程中执行)

[operationB addDependency:operationA]; // 操作B依赖于操作A

如果操作设置了依赖,也给队列设置了maxConcurrentOperationCount = 1。那么操作被执行的顺序取决于依赖。即,依赖的优先级较高。

NSBlockOperation *blkop1 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"执行1 %@",[NSThread currentThread]); }];

NSOperationQueue *queue = [[NSOperationQueue alloc] init];

queue.maxConcurrentOperationCount = 1;

NSBlockOperation *blkop2 = [NSBlockOperation blockOperationWithBlock:^{

NSLog(@"执行2 %@",[NSThread currentThread]); }];

[blkop1 addDependency:blkop2];//blkop1依赖于blkop2

[queue addOperation:blkop1];

[queue addOperation:blkop2];

注意:一定要在操作添加到队列之前设置操作之间的依赖,否则操作已经添加到队列中在设置依赖,依赖不会生效。依赖关系不局限于相同queue中的NSOperation对象,NSOperation对象会管理自己的依赖, 因此不同的操作队列之间的操作也可以设置依赖

队列的取消、暂停、恢复

取消队列的所有操作

- (void)cancelAllOperations;//取消所有操作

提示:也可以调用NSOperation的- (void)cancel方法取消单个操作

暂停和恢复队列

- (void)setSuspended:(BOOL)b; // YES代表暂停队列,NO代表恢复队列

- (BOOL)isSuspended;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息