多线程之NSOperation小结
发布日期:2021-08-16 15:55:10 浏览次数:4 分类:技术文章

本文共 9457 字,大约阅读时间需要 31 分钟。

一、NSOperation 抽象类

  • NSOperation 是一个"抽象类",不能直接使用。抽象类的用处是定义子类共有的属性和方法。
  • NSOperation 是基于 GCD 做的面向对象的封装。
  • 相比较 GCD 使用更加简单,并且提供了一些用 GCD 不是很好实现的功能。
  • 苹果公司推荐使用的并发技术。
  • 两个子类:
    • NSInvocationOperation (调用)
    • NSBlockOperation (块)

相比NSInvocationOperation推荐使用NSBlockOperation,代码简单,同时由于闭包性使它没有传参问题。

  • NSOperationQueue 队列

 

已经学习过的抽象类

  • UIGestureRecognizer
  • CAAnimation
  • CAPropertyAnimation

 

二、 NSOperation 和 GCD 的核心概念

  • GCD的核心概念:将 任务(block) 添加到队列,并且指定执行任务的函数。
  • NSOperation 的核心概念:将 操作 添加到 队列。

三、NSOperation 和 GCD的区别:

GCD

  • 将任务(block)添加到队列(串行/并发/主队列),并且指定任务执行的函数(同步/异步)
  • GCD是底层的C语言构成的API
  • iOS 4.0 推出的,针对多核处理器的并发技术
  • 在队列中执行的是由 block 构成的任务,这是一个轻量级的数据结构
  • 要停止已经加入 queue 的 block 需要写复杂的代码
  • 需要通过 Barrier 或者同步任务设置任务之间的依赖关系
  • 只能设置队列的优先级
  • 高级功能:
    • 一次性 once
    • 延迟操作 after
    • 调度组

NSOperation

  • 核心概念:把操作(异步)添加到队列(全局的并发队列)。
  • OC 框架,更加面向对象,是对 GCD 的封装。
  • iOS 2.0 推出的,苹果推出 GCD 之后,对 NSOperation 的底层全部重写。
  • Operation作为一个对象,为我们提供了更多的选择。
  • 可以跨队列设置操作的依赖关系
  • 可以设置队列中每一个操作的优先级
  • 高级功能:
    • 最大操作并发数(GCD不好做)
    • 继续/暂停/全部取消
    • 跨队列设置操作的依赖关系

四、代码实践

1 //  2 //  ViewController.m  3 //  NSOperationTest  4 //  5 //  Created by mayl on 2018/1/5.  6 //  Copyright © 2018年. All rights reserved.  7 //  8   9 #import "ViewController.h" 10  11 @interface ViewController () 12 @property(nonatomic, strong) NSOperationQueue *gOpQueue; 13 @end 14  15 @implementation ViewController 16  17 - (void)viewDidLoad { 18     [super viewDidLoad]; 19     [self setUpUI]; 20      21 //    [self aysncCon]; 22     [self maxConCount]; 23 //    [self oftenUse]; 24 //    [self setUpDependence]; 25 //    [self waitUntilFinished]; 26 } 27  28 - (void)setUpUI{ 29      30     //暂停,继续按钮 31     UIButton *lBtn4Pause = [UIButton buttonWithType:UIButtonTypeCustom]; 32     [self.view addSubview:lBtn4Pause]; 33      34     lBtn4Pause.frame = CGRectMake(10, 100, 100, 50); 35     [lBtn4Pause setTitle:@"挂起" forState:UIControlStateNormal]; 36     lBtn4Pause.titleLabel.numberOfLines = 0; 37     [lBtn4Pause setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 38     [lBtn4Pause addTarget:self action:@selector(pauseBtnDidClick:) forControlEvents:UIControlEventTouchUpInside]; 39      40     //取消所有任务按钮 41     UIButton *lBtn4CancelAll = [UIButton buttonWithType:UIButtonTypeCustom]; 42     [self.view addSubview:lBtn4CancelAll]; 43      44     lBtn4CancelAll.frame = CGRectMake(150, 100, 100, 50); 45     [lBtn4CancelAll setTitle:@"cancel all" forState:UIControlStateNormal]; 46     [lBtn4CancelAll setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; 47     [lBtn4CancelAll addTarget:self action:@selector(cancelAllBtnDidClick:) forControlEvents:UIControlEventTouchUpInside]; 48 } 49  50 #pragma mark -  action 51  52 /** 53  队列挂起,当前"没有完成的操作",是包含在队列的操作数中的。 54  队列挂起,不会影响已经执行操作的执行状态。 55  队列一旦被挂起,再添加的操作不会被调度。 56  */ 57 - (void)pauseBtnDidClick:(UIButton *)btn{ 58     NSLog(@"队列中操作数:%zd", self.gOpQueue.operationCount); 59     if (0 == self.gOpQueue.operationCount) { 60         NSLog(@"队列中无操作"); 61         return; 62     } 63      64     NSLog(@"3:%d", self.gOpQueue.isSuspended); 65     self.gOpQueue.suspended = !self.gOpQueue.isSuspended; 66     NSLog(@"4:%d", self.gOpQueue.isSuspended); 67     if (self.gOpQueue.isSuspended) { 68         NSLog(@"队列挂起"); 69         [btn setTitle:@"继续" 70              forState:UIControlStateNormal]; 71     }else{ 72         NSLog(@"队列继续"); 73         [btn setTitle:@"挂起" 74              forState:UIControlStateNormal]; 75     } 76 } 77  78 /** 79  取消队列中所有的操作。 80  不会取消正在执行中的操作。 81  不会影响队列的挂起状态 82  */ 83 - (void)cancelAllBtnDidClick:(UIButton *)btn{ 84     if (0 == self.gOpQueue.operationCount) { 85         NSLog(@"队列中无操作"); 86         return; 87     } 88      89     NSLog(@"取消队列中所有操作,此方法不会改变队列挂起状态"); 90     [self.gOpQueue cancelAllOperations]; 91      92     NSLog(@"1:%d", self.gOpQueue.isSuspended); 93     self.gOpQueue.suspended = !self.gOpQueue.isSuspended; 94     NSLog(@"2:%d", self.gOpQueue.isSuspended); 95 } 96  97 /** 默认是:异步,并发 */ 98 - (void)aysncCon{ 99     NSOperationQueue *lQueue = [[NSOperationQueue alloc] init];100     for (int i = 0; i < 20; ++i) {101         [lQueue addOperationWithBlock:^{102             [NSThread sleepForTimeInterval:1];103             NSLog(@"%d,%@", i, [NSThread currentThread]);104         }];105     }106 }107 108 /** 最大并发数:The maximum number of queued operations that can execute at the same time.*/109 - (void)maxConCount{110     NSOperationQueue *lQueue = [[NSOperationQueue alloc] init];111     lQueue.maxConcurrentOperationCount = 2;112     for (int i = 0; i < 30; ++i) {113         [lQueue addOperationWithBlock:^{114             [NSThread sleepForTimeInterval:1];115             NSLog(@"%d,%@", i, [NSThread currentThread]);116         }];117     }118     119     self.gOpQueue = lQueue;120 }121 122 /** 常用:子线程耗时,主线程更新UI */123 - (void)oftenUse{124     NSOperationQueue *lQ = [[NSOperationQueue alloc] init];125     126     [lQ addOperationWithBlock:^{127         NSLog(@"耗时操作开始,%@", [NSThread currentThread]);128         [NSThread sleepForTimeInterval:3];129         NSLog(@"耗时操作结束");130         131         [[NSOperationQueue mainQueue] addOperationWithBlock:^{132             NSLog(@"主线程更新UI,%@",133                   [NSThread currentThread]);134         }];135         136     }];137 }138 139 /** 设置依赖 */140 - (void)setUpDependence{141     NSOperationQueue *lQ = [[NSOperationQueue alloc] init];142     143     [lQ addOperationWithBlock:^{144         [NSThread sleepForTimeInterval:1];145         NSLog(@"do something,%@",146               [NSThread currentThread]);147     }];148     149     NSBlockOperation *lOp1 = [NSBlockOperation blockOperationWithBlock:^{150         [NSThread sleepForTimeInterval:1];151         NSLog(@"1:登录,%@",152               [NSThread currentThread]);153     }];154     155     NSBlockOperation *lOp2 = [NSBlockOperation blockOperationWithBlock:^{156         [NSThread sleepForTimeInterval:1];157         NSLog(@"2:购买点券,%@",158               [NSThread currentThread]);159     }];160     161     NSBlockOperation *lOp3 = [NSBlockOperation blockOperationWithBlock:^{162         [NSThread sleepForTimeInterval:1];163         NSLog(@"3:使用点券,%@",164               [NSThread currentThread]);165     }];166     167     NSBlockOperation *lOp4 = [NSBlockOperation blockOperationWithBlock:^{168         [NSThread sleepForTimeInterval:1];169         NSLog(@"4:返回结果,%@",170               [NSThread currentThread]);171     }];172     173     [lOp2 addDependency:lOp1];174     [lOp3 addDependency:lOp2];175     [lOp4 addDependency:lOp3];176     177     //下面加的话会循环依赖,导致任何操作都无法进行,程序不会崩溃。178 //    [lOp1 addDependency:lOp4];179     180     [lQ addOperations:@[lOp4, lOp3] waitUntilFinished:NO];181     [lQ addOperations:@[lOp2, lOp1] waitUntilFinished:NO];182 }183 184 /**执行效果如下:185  2018-01-05 19:54:31.721539+0800 NSOperationTest[578:156322] come in186  2018-01-05 19:54:33.727691+0800 NSOperationTest[578:156342] 0:do others,
{number = 3, name = (null)}187 2018-01-05 19:54:34.731836+0800 NSOperationTest[578:156342] 1:登录,
{number = 3, name = (null)}188 2018-01-05 19:54:35.737375+0800 NSOperationTest[578:156342] 2:购买点券,
{number = 3, name = (null)}189 2018-01-05 19:54:36.742936+0800 NSOperationTest[578:156342] 3:使用点券,
{number = 3, name = (null)}190 2018-01-05 19:54:37.746491+0800 NSOperationTest[578:156342] 4:show Time,
{number = 3, name = (null)}191 2018-01-05 19:54:38.764408+0800 NSOperationTest[578:156341] 5:[lQ addOperations:@[lOp4, lOp3] waitUntilFinished:YES];实现了不设置依赖,且我需要最后执行,
{number = 4, name = (null)}192 */193 - (void)waitUntilFinished{194 NSOperationQueue *lQ = [[NSOperationQueue alloc] init];195 196 NSLog(@"come in");197 NSBlockOperation *lOp0 = [NSBlockOperation blockOperationWithBlock:^{198 [NSThread sleepForTimeInterval:2];199 NSLog(@"0:do others,%@",200 [NSThread currentThread]);201 }];202 203 NSBlockOperation *lOp1 = [NSBlockOperation blockOperationWithBlock:^{204 [NSThread sleepForTimeInterval:1];205 NSLog(@"1:登录,%@",206 [NSThread currentThread]);207 }];208 209 NSBlockOperation *lOp2 = [NSBlockOperation blockOperationWithBlock:^{210 [NSThread sleepForTimeInterval:1];211 NSLog(@"2:购买点券,%@",212 [NSThread currentThread]);213 }];214 215 NSBlockOperation *lOp3 = [NSBlockOperation blockOperationWithBlock:^{216 [NSThread sleepForTimeInterval:1];217 NSLog(@"3:使用点券,%@",218 [NSThread currentThread]);219 }];220 221 NSBlockOperation *lOp4 = [NSBlockOperation blockOperationWithBlock:^{222 [NSThread sleepForTimeInterval:1];223 NSLog(@"4:show Time,%@",224 [NSThread currentThread]);225 }];226 227 NSBlockOperation *lOp5 = [NSBlockOperation blockOperationWithBlock:^{228 [NSThread sleepForTimeInterval:1];229 230 NSLog(@"5:[lQ addOperations:@[lOp4, lOp3] waitUntilFinished:YES];实现了不设置依赖,且我需要最后执行,%@",231 [NSThread currentThread]);232 }];233 234 [lOp2 addDependency:lOp1];235 [lOp3 addDependency:lOp2];236 [lOp4 addDependency:lOp3];237 238 //执行顺序跟在数组中的顺序无关239 //waitUntilFinished:If YES, the current thread is blocked until all of the specified operations finish executing. If NO, the operations are added to the queue and control returns immediately to the caller.(If YES,当前线程会被阻塞,直到数组中所有操作执行完毕。下局代码是直到lOp5执行完毕,才会执行后续操作)240 [lQ addOperations:@[lOp0] waitUntilFinished:YES];241 242 [lQ addOperations:@[lOp2, lOp1] waitUntilFinished:NO];243 [lQ addOperations:@[lOp4, lOp3] waitUntilFinished:YES];244 245 [lQ addOperation:lOp5];246 }247 248 @end

 

转载于:https://www.cnblogs.com/Dast1/p/8204460.html

转载地址:https://blog.csdn.net/weixin_30810239/article/details/98551577 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:mongodb中获取图片文件<标记>
下一篇:hdu 2710 水题

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年03月10日 09时24分33秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

java中跳出当前循环怎么做_在java中,如何跳出当前的多重循环? 2019-04-21
java程序中执行maven_java – 将一个enviornment变量传递给Maven中的已执行进程 2019-04-21
java16下载_java lombok下载 2019-04-21
python 图像处理与识别书籍_Python图像处理之识别图像中的文字(实例讲解) 2019-04-21
java安全初始化_java安全编码指南之:声明和初始化 2019-04-21
java jstat gc_分析JVM GC及内存情况的方法 2019-04-21
php pclzip.lib.php,php使用pclzip类实现文件压缩的方法(附pclzip类下载地址) 2019-04-21
php dns更新,php_mzdns: 站群,大量域名 通过 dns 服务商 api 批量添加 ip 工具。你懂的~ 基于 mzphp2 框架。... 2019-04-21
jdk 1.8 java.policy,JDK1.8 导致系统报错:java.security.InvalidKeyException:illegal Key Size 2019-04-21
php linux权限,Linux权限详细介绍 2019-04-21
典型环节的matlab仿真分析,典型环节的MATLAB仿真.doc 2019-04-21
Php contenttype类型,各种类型文件的Content Type 2019-04-21
php使用redis持久化,redis如何持久化 2019-04-21
php7.1解压包安装,【Swoole】php7.1安装swoole扩展 2019-04-21
linux centos删除安装的包,CentOS yum认为已删除的软件包仍在安装中 2019-04-21
酒店管理系统c语言带注释,酒店管理系统--C语言版.pdf 2019-04-21
c语言 实现sizeof功能,C语言简单实现sizeof功能代码 2019-04-21
c语言sin函数近似值,用泰勒公式求sin(x)的近似值 2019-04-21
c 语言登录系统源代码,c语言源代码---------------个人图书管理系统 2019-04-21
android线程通信方式,Android 主线程和子线程通信问题 2019-04-21