文档章节

NSOperation那些事

dashL
 dashL
发布于 2014/04/11 17:51
字数 1897
阅读 385
收藏 1
点赞 0
评论 0

iOS中多线程编程主要有三种方式,1)Thread,2)NSOperation与NSOperationQueue,3)GCD,本文简要的介绍一下我理解中的Thread和NSOperation与NSOperationQueue,重点在于介绍NSOperation和NSOperationQueue~

1)NSThread

NSThread,主要有三种创建方式,

- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument
- (void)performSelectorInBackground:(SEL)selector withObject:nil];

前面两种会显示的创建一个Thread,后一种方法则是NSObject (NSThreadPerformAdditions)的实例方法,当调用这种方法的时候,系统会隐式的创建一个Thread。

Thread的缺点是使用者必须手动去管理,并通过加锁等方式确保线程同步,iOS中有两种加锁方式,即NSLock与NSCondition,之后又通过@synchronized替代了NSLock复杂的书写方式,确保线程同步。

NSThread通过以下四种方式进行线程之间的通信。

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array NS_AVAILABLE(10_5, 2_0);
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5, 2_0);

2)NSOperation

NSOperation是一个基类,你可以通过继承的方式,独立创建子Operation,或者通过实例化NSBlockOperation或者NSInvocationOperation使用operation。

查看NSOperation的官方文档,对下面property及method进行解释。

1)- (id)init;//NSOperation实例初始化方法,用于创建一个NSOperation实例。
2)- (void)start;//该方法是operation的起点,如果需要创建并发operation必须,覆盖start方法。同时调用start方法,会默认做各种验证。
3)- (BOOL)isCancelled;//该property,是用于标示某个operation是否cancel。对于多线程来说需要不断检测这个值。
4)- (void)cancel;//调用cancel方法会取消一个operation,但是如果operation加入到Queue中或者operation已经start了,则无法取消成功,调用cancel也不一定立即执行cancel操作,需要等待时间周期。
5)- (BOOL)isExecuting;//判定operation是否正在执行。
6)- (BOOL)isFinished;//判定operation是否完成,cancel掉某个operation,也会将该operation的该字段设置成为YES。
7)- (BOOL)isConcurrent;//判定该线程是否是并发线程,即调用该operation的start方法的线程是否与operation所在线程相同。
8)- (BOOL)isReady;//在start方法开始之前,需要确定operation是否ready,默认为YES,如果该operation没有ready,则不会start。
9)- (void)addDependency:(NSOperation *)op;//该方法用于配置operation之间的依赖关系,涉及执行顺序稍后会介绍。如果不是手动调用start去执行operation,一定要在将其加入到Queue之前做好依赖,因为一旦加入到Queue中,其也许很快会执行,依赖关系将不会起作用。
10)- (void)removeDependency:(NSOperation *)op;//相对应add,其为移除两个operation之间的依赖关系。
11)- (NSArray *)dependencies;//获取operation的依赖关系的数组。
12)- (NSOperationQueuePriority)queuePriority;//如果将operation加入到Queue中,设定其在Queue中的优先级,优先级高的先执行的概率大,但并不代表一定会先执行,执行顺序稍后介绍。
13)- (void)setQueuePriority:(NSOperationQueuePriority)p;//setter方法。
14)- (void (^)(void))completionBlock NS_AVAILABLE(10_6, 4_0);//在operation完成之后会调用completionBlock,你可以自定义执行行为。
15)- (void)setCompletionBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);//setter方法
16)- (void)waitUntilFinished NS_AVAILABLE(10_6, 4_0);//设定是否等待operation执行结束,如果为YES,该线程会一直等待operation执行结束,才会执行接下来的代码。
17)- (double)threadPriority NS_AVAILABLE(10_6, 4_0);//设定operation的线程优先级,涉及执行顺序稍后介绍。线程优先级默认为0.5,最低为0,最大为1.即使设定了线程优先级,也只能保证其在main方法范围内有效,operation的其他代码仍然执行在默认线程。
18)- (void)setThreadPriority:(double)p NS_AVAILABLE(10_6, 4_0);setter方法。

手动创建Operation

1)非并发Operation

如果该operation为非并发operation,则只需要重写其main方法,并正确的执行cancel操作即可,需要operation定时检测isCanceled值。

2)并发Operation

如果需要创建一个并发的Operation,并手动执行,则需要重写main,start,isCancelled,isReady,isConcurrent,isFinished,isExcluting,dependency,queuepripority方法,并维护每个property的KVO,同时确保每个property的原子性。

利用NSInvocationOperation或者NSBlockOperation

大多数开发都不需要自己独立创建operation,而只需要创建一个invocationOperation实例或者创建一个BlockOperation实例,之后将其加入到OperationQueue中,网上很多例子,不再赘述。需要注意的一点是,你应该尽量持有operation的引用,而不要让operation的block做数据存储操作,因为operation的线程被Queue持有,而不是自己独立管理线程。

3)NSOperationQueue

你可以假想成NSOperationQueue是一个任务管理队列,你只需要封装好每个任务(operation),然后将其加入到OperationQueue中,其就会在某个时间执行。

- (void)addOperation:(NSOperation *)op;
- (void)addOperations:(NSArray *)ops waitUntilFinished:(BOOL)wait NS_AVAILABLE(10_6, 4_0);
- (void)addOperationWithBlock:(void (^)(void))block NS_AVAILABLE(10_6, 4_0);

上述三种方式,就是将operation加入到queue中,你可以不断的将operation加入到queue中,但是如果operation加入的过多,则调度operation所耗费的时间会大大增加,导致系统性能下降。

- (NSInteger)maxConcurrentOperationCount;//设定queue的最大并发数
- (void)setMaxConcurrentOperationCount:(NSInteger)cnt;//setter方法
- (void)setSuspended:(BOOL)b;//设置queue是否挂起,YES为将该Queue挂起,NO则取消挂起。如果一个queue处于挂起状态,则其不会相应启动任何operation,如果碰巧operation的waituntilfinished设置成为YES,则陷入死锁。
- (BOOL)isSuspended;//判定某个queue是否挂起
- (void)cancelAllOperations;//取消所有operations
- (void)waitUntilAllOperationsAreFinished;//等待所有的operations执行结束
+ (id)currentQueue NS_AVAILABLE(10_6, 4_0);//获取当前的queue
+ (id)mainQueue NS_AVAILABLE(10_6, 4_0);//获取主线程的queue

4)执行顺序

主要介绍所有operation放在同一个Queue中的执行顺序。先上一段测试代码。

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        self.count += 2;
        NSLog(@"o1:%d",self.count);
    }];
    [operation setCompletionBlock:^{
        NSLog(@"o1,finished");
    }];
    NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
        self.count += 1;
        NSLog(@"o2:%d",self.count);
    }];
    [operation2 setCompletionBlock:^{
        NSLog(@"o2,finished");
    }];
    [operation2 addDependency:operation];
    NSOperationQueue *operationQ = [[NSOperationQueue alloc] init];
    [operation2 setQueuePriority:NSOperationQueuePriorityHigh];
    [operation setThreadPriority:0];
    operationQ.maxConcurrentOperationCount = 1;
    NSArray *array = @[operation,operation2];
    [operationQ addOperations:array waitUntilFinished:YES];

在实例代码中,首先设定Queue为单队列,即最大并发数为1。此时主要有两个考虑因素,首先考虑Operation的依赖关系,

[operation2 addDependency:operation];

Operation2依赖于Operation,所以一定是Operation先执行,之后继续执行Operation2,如果将这行代码注释掉,则开始考虑Operation之间的QueuePriority,在本例子中

 [operation2 setQueuePriority:NSOperationQueuePriorityHigh];

Operation2的queuePriority高于Operation,故先执行Operation2,之后再执行Operation,如果再将这行代码注释掉,则考虑加入的先后顺序

 NSArray *array = @[operation,operation2];

operation先于operation2,则会先执行operation,之后再执行operation2。threadPriority,只会影响其在具体线程资源的priority,并不会影响queue的调度顺序。

假设在本例中的OperationQueue的最大并发数为2,则仍然是按照此顺序调度,不过由于最大并发数为2,假设去除依赖关系,所以operation与operation2需要看谁先轮到时间片,谁先谁后则不确定,如果仍旧存在依赖关系,仍旧是operation先执行,operation2后执行,但是哪个先执行完成并不确定。

ps:在本例中采用了blockOperation方式,同时在block中引用了self.count,并将其值打印出来,可以看到其值是乱的,多线程,你还能要求神马呢。。欢迎交流~~

© 著作权归作者所有

共有 人打赏支持
dashL
粉丝 0
博文 5
码字总数 3765
作品 0
哈尔滨
程序员
NSOperation 简介和应用

基本介绍 NSBlockOperation 打印内容 打印纪录 取消操作 [operation cancel]; NSOperation的依赖关系 MyDownloadOperation downloadOp = [[MyDownloadOperation alloc] init]; // MyDownload......

云飞扬v5
2016/11/12
1
0
操作抽象设计-实践

前言 最近在做程序优化和代码总结的工作,在优化和总结的过程中发现,程序中存在着许多重复性的交互代码,特别是在业务逻辑层,虽然业务模块本身具有独立性,各业务模块之间也有比较明确的分...

Delpan
2017/12/18
0
0
并发程序设计——Operation Queues(操作队列)

Cocoa operations以面向对象的形式封装程序中的工作单元,提供异步执行机制。Operations可以独立运行,也可以与Operation Queue协同运行。OS X和IOS中Cocoa应用程序大多运用了operation机制。...

big军
2013/06/04
0
0
玩转iOS开发:iOS中的NSOperation开发(一)

文章分享至我的个人技术博客: cainrun.github.io/15019481375… 之前, 我们花了小段时间就把给摸了个底, 知道了的操作, 不知道大家有没有好好去耍耍, 这次我们再来讲讲, 中的多线程操作. , 它...

CainLuo
2017/08/14
0
0
知其然亦知其所以然-NSOperation并发编程

对于iOS的并发编程, 用的最普遍的就是GCD了, GCD结合Block可以so easy的实现多线程并发编程. 但如果你看一些诸如AFNetworking, SDWebImage的源码, 你会发现它们使用的都是NSOperation, 纳尼?...

金小俊
2015/11/28
0
0
iOS之[多线程:NSOperation]

NSOperation :fa-exclamation-triangle:以下是你需要考虑使用 NSOperation 的一些理由: 1.当你需要取消线程任务时,GCD 无法提供取消任务的操作。而 NSOperation 提供了取消任务的操作; 2.当...

言筱羽
2015/11/23
95
0
【iOS】多线程NSOperation

NSOperation是苹果封装的一套多线程的东西,不像GCD是纯C语言的,这个是OC的。但相比较之下GCD会更快一些,但本质上NSOPeration是多GDC的封装。 一、NSOperation与GCD的比较 GCD是基于c的底层...

xn4545945
2014/07/28
0
0
iOS多线程之NSOperation

1.简介 1.1NSOperation的作用 配合使用NSOperation和NSOperationQueue也能实现多线程编程 1.2NSOperation和NSOperationQueue实现多线程的具体步骤 先将需要执行的操作封装到一个NSOperation...

JlongTian
2016/01/10
33
0
NSOperationQueue

NSOperation的作用配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤先将需要执行的操作封装到一个NSOperation对象中然后将NSO...

5vinsEnt
2016/05/25
10
0
iOS OS X 和 iOS 中的多线程技术-4 (NSOperation)

//联系人:石虎QQ:1224614774昵称:嗡嘛呢叭咪哄 一NSOperation: 1.NSOperation做的事情比 NSThread 更多一些。通过继承 NSOperation,可以使子类获得一些线程相关的特性,进而可以安全地管理线...

石虎132
2017/12/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

机器学习管理平台 MLFlow

最近工作很忙,博客一直都没有更新。抽时间给大家介绍一下Databrick开源的机器学习管理平台-MLFlow。 谈起Databrick,相信即使是不熟悉机器学习和大数据的工程湿们也都有所了解,它由Spark的...

naughty
今天
0
0
idea tomcat 远程调试

tomcat 配置 编辑文件${tomcat_home}/bin/catalina.sh,在文件开头添加如下代码。    CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=7829" Idea端配......

qwfys
今天
1
0
遍历目录下的文件每250M打包一个文件

#!/usr/bin/env python # -*- utf-8 -*- # @Time : 2018/7/20 0020 下午 10:16 # @Author : 陈元 # @Email : abcmeabc@163.com # @file : tarFile.py import os import tarfile import thr......

寻爱的小草
今天
1
0
expect同步文件&expect指定host和要同步的文件&构建文件分发系统&批量远程执行命令

20.31 expect脚本同步文件 expect通过与rsync结合,可以在一台机器上把文件自动同步到多台机器上 编写脚本 [root@linux-5 ~]# cd /usr/local/sbin[root@linux-5 sbin]# vim 4.expect#!/...

影夜Linux
今天
1
0
SpringBoot | 第九章:Mybatis-plus的集成和使用

前言 本章节开始介绍数据访问方面的相关知识点。对于后端开发者而言,和数据库打交道是每天都在进行的,所以一个好用的ORM框架是很有必要的。目前,绝大部分公司都选择MyBatis框架作为底层数...

oKong
今天
13
0
win10 上安装解压版mysql

1.效果 2. 下载MySQL 压缩版 下载地址: https://downloads.mysql.com/archives/community/ 3. 配置 3.1 将下载的文件解压到合适的位置 我最终将myql文件 放在:D:\develop\mysql 最终放的位...

Lucky_Me
今天
2
0
linux服务器修改mtu值优化cpu

一、jumbo frames 相关 1、什么是jumbo frames Jumbo frames 是指比标准Ethernet Frames长的frame,即比1518/1522 bit大的frames,Jumbo frame的大小是每个设备厂商规定的,不属于IEEE标准;...

问题终结者
今天
2
0
expect脚本同步文件expect脚本指定host和要同步的文件 构建文件分发系统批量远程执行命令

expect脚本同步文件 在一台机器上把文件同步到多台机器上 自动同步文件 vim 4.expect [root@yong-01 sbin]# vim 4.expect#!/usr/bin/expectset passwd "20655739"spawn rsync -av ro...

lyy549745
今天
1
0
36.rsync下 日志 screen

10.32/10.33 rsync通过服务同步 10.34 linux系统日志 10.35 screen工具 10.32/10.33 rsync通过服务同步: rsync还可以通过服务的方式同步。那需要开启一个服务,他的架构是cs架构,客户端服务...

王鑫linux
今天
1
0
matplotlib 保存图片时的参数

简单绘图 import matplotlib.pyplot as pltplt.plot(range(10)) 保存为csv格式,放大后依然很清晰 plt.savefig('t1.svg') 普通保存放大后会有点模糊文件大小20多k plt.savefig('t5.p...

阿豪boy
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部