前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS_多线程三:NSOperation的使用

iOS_多线程三:NSOperation的使用

作者头像
mikimo
发布2022-07-20 14:09:24
4910
发布2022-07-20 14:09:24
举报
文章被收录于专栏:iOS开发~

目录

一、NSInvocationOperation

二、NSBlockOperation

三、NSOperationQueue

NSOperation 是一个抽象类,线程安全,不需要添加额外的锁

使用其子类:NSInvocationOperation 和 NSBlockOperation

1、NSInvocationOperation

一个对象,表示一个任务

默认在主线程中同步顺序执行,想要并行异步,需要搭配`NSOperationQueue`使用

同步/异步,通过设置最大并发数`maxConcurrentOperationCount`实现:1:串行 >=2:并行 默认:-1 异步(无穷大)

2、NSBlockOperation

一个对象,可以创建多个任务

blockOperationWithBlock 添加的任务默认在主线程中

addExecutionBlock 添加任务,会开启多个线程,并发执行

一、NSInvocationOperation

一个 NSInvocationOperation 对象表示一个任务,需要手动调用 start 开启。

代码语言:javascript
复制
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(network:) object:@{@"name":@"moxiaohui"}];
[operation setName:@"moxiaoyan"];
[operation setCompletionBlock:^{ // 任务执行完成后在子线程中执行
  NSLog(@"Completion %@", [NSThread currentThread]);
}];
[operation start];
NSLog(@"是否阻塞主线程"); // 会

- (void)network:(NSDictionary *)info {
  NSLog(@"执行 operation %@ %@", [NSThread currentThread], info);
  sleep(2);
  NSLog(@"完成 operation");
}

// 执行结果:
// 执行 operation <NSThread: 0x600000c24040>{number = 1, name = main} {
    name = moxiaohui;
}
// 完成 operation
// 是否阻塞主线程
// Completion <NSThread: 0x600003139680>{number = 4, name = (null)}

从执行结果可以看得出来,默认是在主线程中执行的,而且会阻塞主线程。

若想实现异步并发,需要结合 NSOperationQueue 使用:

代码语言:javascript
复制
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 设置最大并发数: 1:串行 >=2:并行  默认:-1(无穷大)
// 注意:设置的是队列里面最多能并发运行的操作任务个数,而不是线程个数, (另外开启线程的数量是由系统决定的,所以这个值具体表示什么?)
[queue setMaxConcurrentOperationCount:2];
// 将任务添加到队列中
[queue addOperation:operation];
NSLog(@"是否阻塞主线程");

// 执行结果:
// 是否阻塞主线程
// 执行 operation <NSThread: 0x6000005e44c0>{number = 5, name = (null)} {
    name = moxiaohui;
}

NSOperationQueue一些其他的属性和方法:

代码语言:javascript
复制
// 可以设置特殊的先后执行顺序:addDependency
[operation2 addDependency:operation1]; // 添加依赖
[operation3 removeDependency:operation1]; // 移除依赖

[operation start];  // NSInvocationOperation alloc init 创建的需要手动开启
[operation cancel]; // 取消单个任务,只会对还未执行的任务有效
[operation waitUntilFinished]; // 阻塞当前线程,直到任务执行完毕后继续 (最好不要在主线程中等待,会阻塞)
// 观察任务状态:
[operation isReady];  // 是否就绪
[operation isExecuting]; // 是否正在执行中
[operation isFinished]; // 是否执行完毕
[operation isCancelled];  // 是否已取消
[operation isAsynchronous]; // 是否异步执行
[operation isConcurrent]; // 已废弃,用`isAsynchronous`
NSOperationQueuePriority priority = [operation queuePriority]; // 优先级
NSArray<NSOperation *> *dependencies = [operation dependencies]; // 依赖的任务数组

二、NSBlockOperation

代码语言:javascript
复制
NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{ // 默认在主线程中
  NSLog(@"执行2 block %@", [NSThread currentThread]);
  sleep(1);
  NSLog(@"完成2 block");
}];

// 通过 addExecutionBlock 添加的任务,会开辟多个子线程
[block addExecutionBlock:^{
  NSLog(@"执行3 block %@", [NSThread currentThread]);
  sleep(1);
  NSLog(@"完成3 block");
}];
[block addExecutionBlock:^{
  NSLog(@"执行4 block %@", [NSThread currentThread]);
  sleep(3);
  NSLog(@"完成4 block");
}];
[block addExecutionBlock:^{
  NSLog(@"执行5 block %@", [NSThread currentThread]);
  sleep(2);
  NSLog(@"完成5 block");
}];
[block start];
NSLog(@"是否阻塞主线程"); // 会

// 执行结果:
// 执行3 block <NSThread: 0x600003a9cd80>{number = 5, name = (null)}
// 执行2 block <NSThread: 0x600003a982c0>{number = 6, name = (null)}
// 执行5 block <NSThread: 0x600003aced40>{number = 1, name = main}
// 执行4 block <NSThread: 0x600003a97740>{number = 3, name = (null)}
// 完成2 block
// 完成3 block
// 完成5 block
// 完成4 block
// 是否阻塞主线程

从执行结果可以看出来,任务一多,就不确定哪个任务会主线程中执行了,所以感觉还是用queue比较保险

三、NSOperationQueue

NSOperationQueue 操作队列,管理Operation对象,根据Operation开辟适量的线程

代码语言:javascript
复制
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// 设置最大并发数: 1:同步 >=2:异步  默认:-1(无穷大)
// 注意:设置的是队列里面最多能并发运行的操作任务个数,而不是线程个数, (另外开启线程的数量是由系统决定的,所以这个值具体表示什么?)
[queue setMaxConcurrentOperationCount:2];
// 将任务添加到队列中
[queue addOperation:operation];
NSLog(@"是否阻塞主线程");
[queue addOperation:block];
[queue addOperationWithBlock:^{
NSLog(@"执行6 %@", [NSThread currentThread]);
sleep(2);
NSLog(@"完成6");
}];
[queue addBarrierBlock:^{ // 队列中所有任务完成后执行
NSLog(@"all complete");
}];
[queue setSuspended:YES]; // 暂停队列
[queue setSuspended:NO];  // 继续队列
[queue cancelAllOperations]; // 取消所有任务
[queue waitUntilAllOperationsAreFinished]; // 阻塞当前线程,直到所有任务执行完毕后继续(最好不要在主线程中等待,会阻塞)

Demo github 地址

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-01-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、NSInvocationOperation
  • 二、NSBlockOperation
  • 三、NSOperationQueue
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档