iOS_多线程三:NSOperation的使用

目录

一、NSInvocationOperation

二、NSBlockOperation

三、NSOperationQueue


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

使用其子类:NSInvocationOperation 和 NSBlockOperation

1、NSInvocationOperation

一个对象,表示一个任务

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

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

    

2、NSBlockOperation

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

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

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

一、NSInvocationOperation

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

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 使用:

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一些其他的属性和方法:

// 可以设置特殊的先后执行顺序: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

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开辟适量的线程

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 地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

莫小言mo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值