本文章属于原创,转载请注明出处
参考文章
GCD和NSOperationQueue
stackoverflow
NSOperation
NSOperation是对GCD的Block的一个封装,它也表示一个要被执行的任务
let operation = NSBlockOperation { () -> Void in
print(NSTread.currentThread())
}
operation.addExcutionBlock { () -> Void in
print("excution block1 -- \(NSThread.currentThread())")
}
operation.start()
- NSBlockOperation是NSOperation的子类,不应该直接调用NSOperation对象,但可以生成其子类
- NSBlockOperation是苹果预定义的子类,可用用来封装多个Block,使用addExcutionBlock追加Block,使用start来让任务开始执行
NSOperationQueue
- 默认的NSOperation是同步执行的,NSOperation有一个只读属性asynchronous,这意味着想要异步执行,就要自定义NSOperation的子类,或使用NSOperationQueue
- GCD有三种队列,主队列,串行队列,并行队列。NSOperationQueue更简单,只有两种,主队列和非主队列
- 自己生成的都是非主队列,主队列需要使用NSOperationQueue.mainQueue取得
- NSOperationQueue的主队列是串行队列,而且其中所有NSOperation都会在主线程中执行
- 对于非主队列来说,一旦一个NSOperation被加入其中,那么都是并发执行的,因为NSOperationQueue会为每个NSOperation创建线程并调用start方法
- NSOperationQueue有个属性叫maxConcurrentOperationCount,表示它最多支持几个NSOperation并发执行,如果为1,则这个队列就是串行队列
使用NSOperationQueue实现并行操作
let operationQueue = NSOperationQueue()
let operation = NSBlockOperation()
operation.addExcutionBlock { () -> Void in
print("exec block1 -- \(NSTread.currentThread)")
}
operation.addExcutionBlock { () -> Void in
print("exec block2 -- \(NSThread.currentThread)")
}
operation.addExcutionBlock { () -> Void in
print("exec block3 -- \(NSThread.currentThread)")
}
operationQueue.addOperation(operaion)
print("操作结束")
使用NSOperationQueue来执行任务和前面的区别在于,首先创建一个非主队列,然后调用addOperation方法替换前面的start,因为NSOperationQueue在将NSOperation加入队列时,会自动调用start方法
NSOperation新特性
NSOperation是对GCD更上层的封装,它有着GCD很难实现的特性,由于NSOperaiton和NSOperationQueue良好的封装,这些新特性用起来都非常简单
- 取消任务
operation.cancel()
operation.cancelAllOperations()
- 设置依赖
比如当两个并发的operation在执行网络请求时,operation2的执行依赖于operation1的数据,所以要保证operation2执行的时候,operation1已经执行完成了,同时还需要NSOperationQueue的并发特性,因为还可能有别的任务也在执行
operation2.addDependency(operation1)
但在使用时要注意,有可能引起死锁
- 暂停与恢复
queue.suspended = true
queue.suspended = false
// 暂停或者恢复所有的operation
- 设置优先级
public enum NSOperationQueuePriority: Int {
case VeryLow
case Low
case Normal
case High
case VeryHigh
}
但NSOperationQueue并不能保证优先级高的一定先执行
NSOpreation Queue & GCD
- GCD是纯C的API,任务用块表示,块是个轻量级数据结构,操作队列是Objective-C对象
使用NSOperation和NSOperationQueue的好处如下
- 取消某个操作。使用操作队列取消操作很容易,任务执行前,使用cancel方法,表明此任务不需要执行,已启动的任务无法取消,不使用操作队列,在GCD中无法取消
- 指定操作间依赖关系。可以指定依赖体系,让一个操作执行完以后才能执行另一个
- 通过KVO来监控NSOperation对象的属性。NSOperation对象有许多属性都适合通过KVO来监听,比如可以通过isCanceled属性来判断任务是否取消,isFinished属性来判断任务是否完成
- 指定操作的优先级。GCD也可以设定优先级,但是是对整个队列设定优先级,而不是对
块
设定,NSOperation使用这个操作只需要一个属性 - 复用NSOperation对象。系统内有不少NSOperation的子类供开发者使用,不想用的话可以自己创建,这些类是普通的Objective-C对象,能存放任何信息,对象在执行时可以充分利用其中的信息,而且可以随意调整类的方法,这些NSOperation对象可以在代码中多次使用
- 一般来说要使用更高级别的操作,也就是说要使用NSOperationQueue而不是GCD,除非所做的操作GCD不支持,有很多事可以使用NSOperationQueue来完成,而使用GCD需要写很多代码,另一方面,如果所做的仅仅是完成一个Block,那么使用GCD来做是更方便的