我所知道的NSOpeartionQueue知识
OC里面的多线程,主要是GCD和NSOpeartionQueue两种,上一篇文章主要介绍了GCD(我所知道的GCD知识),这一篇主要是介绍NSOpeartionQueue
首先我们需要先了解一下NSOpeartion这个类
NSOpeartion opeartion是操作的意思,这个类就是苹果帮我们封装的一个操作类。看一下苹果文档的介绍
An abstract class that represents the code and data associated with a single task.
Because the NSOperation class is an abstract class, you do not use it directly but instead subclass or use one of the system-defined subclasses (NSInvocationOperation or NSBlockOperation) to perform the actual task. Despite being abstract, the base implementation of NSOperation does include significant logic to coordinate the safe execution of your task. The presence of this built-in logic allows you to focus on the actual implementation of your task, rather than on the glue code needed to ensure it works correctly with other system objects.
An operation object is a single-shot object—that is, it executes its task once and cannot be used to execute it again. You typically execute operations by adding them to an operation queue (an instance of the NSOperationQueue class). An operation queue executes its operations either directly, by running them on secondary threads, or indirectly using the libdispatch library (also known as Grand Central Dispatch). For more information about how queues execute operations, see NSOperationQueue.
If you do not want to use an operation queue, you can execute an operation yourself by calling its start method directly from your code. Executing operations manually does put more of a burden on your code, because starting an operation that is not in the ready state triggers an exception. The ready property reports on the operation’s readiness.
上面主要说的是:NSOpeartion类是一个抽象基类,是用来关联一个单独的任务。后面说的主要是我们需要使用它的子类NSInvocationOperation
or NSBlockOperation
或者自己去写一个子类。用这些子类配合NSOpeartionQueue去使用。后面的我就翻译了,大家可以直接有道翻译。
经过上面的介绍后,我们大致知道了这个类是用来关联任务的,下面我们一起看一下苹果提供的api
当然我们如果使用的话,还是先看它对应的子类NSInvocationOperation
和NSBlockOperation
NSOpeartion使用
NSInvocationOperation
调用操作类,api比较简单,就不帖了,使用如下:
NSBlockOperation
block类型的操作类,使用如下:
不知道大家注意没,上面两个图上都输出了任务执行所在的线程,这两种操作执行的任务都是在主线程执行的。我自己私下里做过试验,一般在哪条线程上创建的operation,其所执行的任务是会默认在这条线程上执行。
例如:
当然NSBlockOperation
这个类,还有一个添加任务的方法addExecutionBlock:
,这个方法比较特殊。添加的任务不是在当前所在线程执行的。这个大家要注意一下
自己初始化一个NSOpeartion子类
创建一个继承NSOpeartion的子类MSOperation。主要是重写-(void)main
方法,如下:
-(void)main {
NSLog(@"我是:雨天多久就");
}
上面是NSOpeartion的简单使用方法。但是一般我们使用NSOpeartion都是配合着NSOpeartionQueue使用的
流程是:创建operation,然后把这个operation加入到NSOpeartionQueue队列中
注意看,加入到Queue中的opeartion是不需要再调用start方法才执行任务
另外,需要注意的是Queue的生成有两种方式:1.alloc init
2.[NSOperationQueue mainQueue]
获取主队列
-
通过
alloc init
方式创建的队列,默认是并发队列因为Queue的属性
maxConcurrentOperationCount
默认是-1我们可以设置maxConcurrentOperationCount来决定同时间的任务执行数(最大并发数)
因此,当我们设置这个属性值是1的时候,这个队列里的任务是一条一条顺序执行的
如下图:
而当我们不设置这个
maxConcurrentOperationCount
值的时候,队列里的任务是多条线程,并发执行 -
通过
[NSOperationQueue mainQueue]
获取主队列,任务都是在主线程执行maxConcurrentOperationCount
值设置不起作用
经过上面的介绍,我们会发现,这个Queue和GCD几乎也是一样的。
NSOpeartion 就类似 dispatch_async_函数后面跟着的block
NsopeartionQueue 就是 dispatch_async_函数后面参数里的queue
我觉得,NSOpeartionQueue对于复杂一点的操作比较合适。GCD也很方便,但是我一般都是简单的操作使用
使用OpeartionQueue,我们可以对队列里的任务进行依赖设置、取消等操作
- 依赖设置
虽然GCD也可以实现这种,但是我觉得在代码简洁上,还是这种方式更好
- 取消
直接调用cancelAllOperations
就可以将还未执行的任务取消掉