NSOperation学习

2021-09-14  本文已影响0人  小李不木

1). NSOperation是基于GCD之上的更高一层封装, 拥有更多的API (e.g. suspend, resume, cancel等等).

2). 在NSOperationQueue中, 可以指定各个NSOperation之间的依赖关系.

3). 用KVO可以方便的监测NSOperation的状态(isExecuted, isFinished, isCancelled).

4). 更高的可定制能力, 你可以继承NSOperation实现可复用的逻辑模块. 3种子类的使用以及和队列queue的配合使用

4). 设置最大并发数

1). 串行(Serial) VS. 并行(Concurrent)

串行和并行描述的是任务和任务之间的执行方式. 串行是任务A执行完了任务B才能执行, 它们俩只能顺序执行. 并行则是任务A和任务B可以同时执行.

2). 同步(Synchronous) VS. 异步(Asynchronous)

同步和异步描述的其实就是函数什么时候返回. 比如用来下载图片的函数A: {download image}, 同步函数只有在image下载结束之后才返回, 下载的这段时间函数A只能搬个小板凳在那儿坐等... 而异步函数, 立即返回. 图片会去下载, 但函数A不会去等它完成. So, 异步函数不会堵塞当前线程去执行下一个函数!

平常说的并发编程包括狭义上的"并行"和"并发",  不能保证代码会被并行执行, 但可以以并发的方式设计代码. 系统会判断在某一个时刻是否有可用的core(多核CPU核心), 如果有就并行(parallelism)执行, 否则就用context switch来分时并发(concurrency)执行. 

NSOperation有三个状态量isCancelled,isExecuting和isFinished. 

NSOperation的子类化一般都是采取重写start 或者 main方法。

队列中调用cancel而进入队列的nsoperation一定要等当前operation执行完,然后暂停其他的operation

1. 重写main不用关心operation对象的释放问题,不要处理任务状态,main会多次调用,串行方法重写main , main函数执行完成后, isExecuting会被置为NO, 而isFinished则被置为YES.

2. 重写start方法需要主动调用main方法,并行方法重新 start 

为了防止外部多次调用[operation start]方法,重写start方法需要 对 blockoperation 的 isfinished 状态进行判断,如果  isfinished=yes,就不会执行了,必须处理好isExecuting,  isFinished, isConcurrent 和 isReady这些属性。

关于start方法与main方法的执行时机,可以粗略这样理解:operation加入queque时直接执行main,不调用start;调用start方法时,在start方法中调用main方法。

NSOperation默认是非并发的:

NSOperation调用start方法即可开始执行操作,NSOperation对象默认按同步方式执行,也就是在调用start方法的那个线程中直接执行。NSOperation对象的isConcurrent方法会告诉我们这个操作相对于调用start方法的线程,是同步还是异步执行。isConcurrent方法默认返回NO,表示操作与调用线程同步执行

怎么实现并发(concurrent)的NSOperation呢? 也很简单:

1). 重写isConcurrent函数, 返回YES, 这个告诉系统各单位注意了我这个operation是要并发的.

2). 重写start()函数.

3). 重写isExecuting和isFinished函数子类化NSOperation

为什么在并发情况下需要 设定isExecuting和isFinished这两个状态量呢? 

在并发情况下系统不知道operation什么时候finished, operation里面的task一般来说是异步执行的, 也就是start函数返回了operation不一定就是finish了, 这个需要自己来控制, 什么时候将isFinished置为YES(发送相应的KVO消息), operation就什么时候完成了.

注意点:1,重写main方法和start方法区别

重写start方法,在start方法中可以做判断如果isfinished就return,防止多次调用,而且里面需要主动调用main方法

注意:

在ios4以前,只有非并发的情况下,队列会为operation开启一个线程来执行。如果是并发的情况,operation需要自己创建一个线程来执行。所以说,NSoperation的并发和非并发不是传统意义上的串行和并行。

但是在ios4以后,不管是并发还是非并发,队列都会为operation提供一个线程来执行。所以isConcurrent这个变量也就没有用处了。

但是,这里还设涉及到了两个方法,start和main.

按照官方文档所说,如果是非并发就使用main,并发就使用start。

那现在并发和非并发已经没有区别了,start和main的区别在哪里呢?

main方法的话,如果main方法执行完毕,那么整个operation就会从队列中被移除。如果你是一个自定义的operation并且它是某些类的代理,这些类恰好有异步方法,这是就会找不到代理导致程序出错了。

然而start方法就算执行完毕,它的finish属性也不会变,因此你可以控制这个operation的生命周期了。

然后在任务完成之后手动cancel掉这个operation即可。

参考:

[iOS]NSOperation的start与main,并发与非并发。_wcxdell的专栏-CSDN博客

iOS中NSOperation详解 - 简书

多线程之NSOperation进阶用法 - 简书

自定义NSOperation_MeteoriteMan的博客-CSDN博客

上一篇 下一篇

猜你喜欢

热点阅读