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

多线程之NSOperation小结

作者头像
woopDast1
发布2020-09-04 10:39:26
4340
发布2020-09-04 10:39:26
举报
文章被收录于专栏:iOSeriOSer

一、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不好做)
    • 继续/暂停/全部取消
    • 跨队列设置操作的依赖关系

四、代码实践

代码语言:javascript
复制
  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 in
186  2018-01-05 19:54:33.727691+0800 NSOperationTest[578:156342] 0:do others,<NSThread: 0x1c027f740>{number = 3, name = (null)}
187  2018-01-05 19:54:34.731836+0800 NSOperationTest[578:156342] 1:登录,<NSThread: 0x1c027f740>{number = 3, name = (null)}
188  2018-01-05 19:54:35.737375+0800 NSOperationTest[578:156342] 2:购买点券,<NSThread: 0x1c027f740>{number = 3, name = (null)}
189  2018-01-05 19:54:36.742936+0800 NSOperationTest[578:156342] 3:使用点券,<NSThread: 0x1c027f740>{number = 3, name = (null)}
190  2018-01-05 19:54:37.746491+0800 NSOperationTest[578:156342] 4:show Time,<NSThread: 0x1c027f740>{number = 3, name = (null)}
191  2018-01-05 19:54:38.764408+0800 NSOperationTest[578:156341] 5:[lQ addOperations:@[lOp4, lOp3] waitUntilFinished:YES];实现了不设置依赖,且我需要最后执行,<NSThread: 0x1c04631c0>{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
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-01-05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

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

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

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

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