多线程 (五)NSOperation
2016-02-09 12:54
330 查看
NSOperation是对GCD的分装,OC语言,更简单方便
NSOperation和NSOperationQueue一起使用也能实现多线程编程
基本步骤:
将操作封装到一个NSOperation对象中
将NSOperation对象添加到NSOperationQueue队列
系统会将NSOperationQueue中的NSOperation取出
将取出的NSOperation封装的操作放到一条新线程中执行
NSOperation是一个抽象类,不具备操作能力,必须使用它的子类:
NSInvocationOperation
NSBlockOperation(使用的最多)
自定义子类继承于NSOperation,实现相应的方法(使用较少)
1.NSInvocationOperation:
打印可以验证queue是一个并发队列
2.NSBlockOperation
也可以这样使用(更简单)
添加一个额外的操作
NSOperationQueue:
NSOperationQueue没有串行队列,但是它可以获取主队列,通过下面代码获取到主队列,添加到主队列中的任务都会在主线程中执行
线程间通讯 :
最大并发数:
并发数是指同时执行任务的数量
比如同时开启3个线程执行3个任务,并发数就是3
NSOperation可以通过最大并发数控制同一时间执行操作数量
结果出现了2,3,4,5四个线程,这是因为最大并发决定的是同一时间执行操作数量,而不是线程的数量;
挂起队列:
挂机队列是把任务保存在当前状态,之后可以继续
挂起操作不会影响已经在执行的任务
取消操作
取消操作并不会影响队列的挂起状态
(如果队列是挂起状态)一般取消操作后会把队列置于不挂起状态,便于后续操作
挂起队列,队列中的任务还存在,可以继续;取消操作,队列中的任务就没有了,只能重新添加任务
打印结果可以看出后面的操作都已经被取消了
依赖关系 :
依赖关系可以跨队列
注意不要循环依赖
NSOperation和NSOperationQueue一起使用也能实现多线程编程
基本步骤:
将操作封装到一个NSOperation对象中
将NSOperation对象添加到NSOperationQueue队列
系统会将NSOperationQueue中的NSOperation取出
将取出的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(@"听完音乐放松一下"); }
相关文章推荐
- NGINX301 REWRITE官方博客文档
- 【Linux相关】linux大文件分割与合并
- JSF适合开发网站吗?
- 在线弹幕xml文件转ass 附:在线转换其他文件格式的网站
- 吊扇项目总结(三)— 嵌入式软件架构MVC模式
- AVD之PANIC: Could not open ***
- 3.以普通表格型单表为模板定制模块:短信库维护
- 基于Android arm64 Linux got 调试_02
- document.documentElement和document.body的 scrollHeight/scrollTop/clientHeight 以及判断滚动条是否已拉到页面最底部
- 嵌入式linux中nRF24L01驱动(主控板tiny4412)
- 【Nginx笔记】nginx配置文件具体解释
- Kali 获取WEP无线密码过程
- ubuntu14.04 配置tomcat8
- Linux文件系统基础(1)
- 大型网站架构系列:负载均衡详解(3)
- 大型网站架构系列:负载均衡详解(1)
- 大型网站架构系列:电商网站架构案例(3)
- 大型网站架构系列:电商网站架构案例(1)
- 大型分布式网站架构技术总结
- linux 信号 alarm和pause