NSOperation是对GCD的分装,OC语言,更简单方便

NSOperation和NSOperationQueue一起使用也能实现多线程编程

基本步骤:

  1. 将操作封装到一个NSOperation对象中
  2. 将NSOperation对象添加到NSOperationQueue队列
  3. 系统会将NSOperationQueue中的NSOperation取出
  4. 将取出的NSOperation封装的操作放到一条新线程中执行

NSOperation是一个抽象类,不具备操作能力,必须使用它的子类:

  • NSInvocationOperation
  • NSBlockOperation(使用的最多)
  • 自定义子类继承于NSOperation,实现相应的方法(使用较少)

1.NSInvocationOperation:

- (void)InvocationOperation
{
//创建队列,通过alloc init方式创建的队列是并发队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

   for(int i = 0; i < 5; i++)
{
//创建操作
NSInvocationOperation *op = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test) object:nil];
//把操作放到队列中
[queue addOperation:op];
}
} - (void)test
{
NSLog(@"当前线程 = %@",[NSThread currentThread]);
}

打印可以验证queue是一个并发队列

2.NSBlockOperation

- (void)BlockOperation
{
//创建队列,通过alloc init方式创建的队列是并发队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init]; for(int i = 0; i < 5; i++)
{
//创建操作
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"当前线程 = %@",[NSThread currentThread]);
}];
//把操作放到队列中
[queue addOperation:op];
}
}

也可以这样使用(更简单)

- (void)BlockOperationEasy
{
//创建队列,通过alloc init方式创建的队列是并发队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
NSLog(@"当前线程 = %@",[NSThread currentThread]);
}];
}

添加一个额外的操作

- (void)BlockOperation
{
//创建队列,通过alloc init方式创建的队列是并发队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//创建操作
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"当前线程 = %@",[NSThread currentThread]);
}];
//再添加一个操作
[op addExecutionBlock:^{
NSLog(@"这是一个额外的操作,线程 = %@",[NSThread currentThread]);
}];
//把操作放到队列中
[queue addOperation:op]; }

NSOperationQueue:

NSOperationQueue没有串行队列,但是它可以获取主队列,通过下面代码获取到主队列,添加到主队列中的任务都会在主线程中执行

 [NSOperationQueue mainQueue]

线程间通讯 :

- (void)refreshUI
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
NSLog(@"多线程中执行的操作%@",[NSThread currentThread]);
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"回到主线程更新UI%@",[NSThread currentThread]);
}];
}];
}

最大并发数:

  • 并发数是指同时执行任务的数量
  • 比如同时开启3个线程执行3个任务,并发数就是3
  • NSOperation可以通过最大并发数控制同一时间执行操作数量
- (void)max
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 2;
for (int i = 0; i< 10; i++)
{
[queue addOperationWithBlock:^{
NSLog(@"i = %d, thread = %@",i,[NSThread currentThread]);
}];
}
}

结果出现了2,3,4,5四个线程,这是因为最大并发决定的是同一时间执行操作数量,而不是线程的数量;

挂起队列:

  • 挂机队列是把任务保存在当前状态,之后可以继续
  • 挂起操作不会影响已经在执行的任务
- (void)suspended
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
for (int i = 0; i< 10; i++)
{
if (i == 5)
{
//挂起队列
queue.suspended = YES;
//延迟2s
[NSThread sleepForTimeInterval:2];
//继续
queue.suspended = NO;
}
[queue addOperationWithBlock:^{ NSLog(@"i = %d, thread = %@",i,[NSThread currentThread]);
}];
}
}

取消操作

  • 取消操作并不会影响队列的挂起状态
  • (如果队列是挂起状态)一般取消操作后会把队列置于不挂起状态,便于后续操作
  • 挂起队列,队列中的任务还存在,可以继续;取消操作,队列中的任务就没有了,只能重新添加任务
- (void)cancel
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
//设置最大并发数为1
queue.maxConcurrentOperationCount = 1;
for (int i = 0; i< 10; i++)
{
[queue addOperationWithBlock:^{
[NSThread sleepForTimeInterval:1];
NSLog(@"i = %d, thread = %@",i,[NSThread currentThread]);
}];
}
//3S后取消队列里的所有操作
[NSThread sleepForTimeInterval:3];
[queue cancelAllOperations];
}

打印结果可以看出后面的操作都已经被取消了

依赖关系 :

  • 依赖关系可以跨队列
  • 注意不要循环依赖
- (void)dependecy
{
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSBlockOperation *one = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载音乐");
}];
NSBlockOperation *two = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"打开音乐");
}];
NSBlockOperation *three = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"播放音乐");
}];
//添加任务依赖关系
[two addDependency:one];
[three addDependency:two]; //等待任务完成继续下一个任务,类似于GCD里的调度组
[queue addOperations:@[one,two,three] waitUntilFinished:YES];
NSLog(@"听完音乐放松一下");
}

  

最新文章

  1. 介绍一款原创的四则运算算式生成器:CalculateIt2
  2. CentOS6.3安装MongoDB2.2 及 安装PHP的MongoDB客户端
  3. Android基础开发文档汇总
  4. iOS图片加载框架-SDWebImage解读
  5. Integrated Circuit Intro
  6. Codeforces Round #156 (Div. 2)
  7. UItableview里面的header、footer
  8. Hash(哈希)
  9. Hibernate与MyBatis区别
  10. The type sun.management.ManagementFactory is not visible
  11. Android数据库的使用
  12. Android带头像的用户注册页面
  13. C++11于once_flag,call_once分析的实现
  14. RDA5820收音机芯片驱动
  15. Java集合干货——ArrayList源码分析
  16. nyoj 数的长度
  17. Dell台式机Window10恢复重装window7步骤
  18. C#WebApi 接口参数不再困惑:传参详解
  19. 00centos安装
  20. SSL和TLS协议的区别

热门文章

  1. sublime text3 针对于前端开发必备的插件
  2. 学习之spring属性文件注入
  3. 【转载】Linux小白福利:《超容易的Linux系统管理入门书》(三)在虚拟机上安装Linux
  4. Android开发虚拟机的各种分辨率
  5. feature.shape和feature.shapecopy的区别
  6. [设计模式]NetworkManagementService中的观察者模式
  7. mysql 触发器,insert,auto字段竟然一样....
  8. CSS3单位
  9. java将多个连续的空格转化成一个空格
  10. MongoDB的安全性