第43条:掌握GCD及操作队列的使用时机
1.从一个方法(NSNotificationCenter)中认识操作队列:
- NSOperationQueue:可以把操作以NSOperation子类的方式放在队列中,也能够并发执行
- (id <NSObject>)addObserverForName:(nullable NSString *)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block NS_AVAILABLE(10_6, 4_0);
2.区分GCD和NSOperationQueue:
(1)GCD是纯C的API,GCD任务用块表示
(2)操作队列是OC的对象,操作队列是更为重量级的OC对象
3.用NSOperationQueue类的”addOperationWithBlock:”方法搭配NSBlockOperation类来使用操作队列。好处如下:
(1)取消某个操作。如果使用操作队列,那么想要取消操作队列是很容易的。运行任务之前,可以在NSOperation对象上调用cancel方法,该方法会设置对象内的标志位,用以表明此任务不需执行,不过,已经启动的任务无法取消。若是不使用操作队列,而是把块安排到GCD队列,那就无法取消了。开发者可以在应用程序层自己来实现取消功能,不过这样做需要编写很多代码,而那些代码其实已经由操作队列实现好了。
(2)指定操作间的依赖关系。一个操作可以依赖其他多个操作。开发者能够制定操作之间的依赖体系,使特定的操作必须在另外一个操作顺利执行完毕后方可执行。
(3)通过键值观测机制监控NSOperation对象的属性。NSOperation对象有许多属性都适合通过键值观测机制(简称KVO)来监听。比如可以通过isCancelled属性来判断任务是否已取消,又比如可以通过isFinished属性来判断任务是否已完成。
(4)指定操作的优先级。操作的优先级表示此操作与队列中其他操作之间的优先级关系。优先级高的操作先执行,优先级低的后执行。操作队列的调度算法(scheduling algorithm)虽“不透明”(opaque),但必然是经过一番深思熟虑才写成的。反之,GCD则没有直接实现此功能的办法。GCD的队列确实有优先级,不过那是针对整个队列来说的,而不是针对每个块来说的。NSOperation对象也有“线程优先级”(thread priority),这决定了运行此操作的线程处在何种优先级上。用GCD也可实现此功能,然而采用操作队列更简单,只需设置一个属性。
(5)重用NSOperation对象。系统内置了一些NSOperation的子类(比如NSBlockOperation)以供开发者调用,要是不想用这些固有子类的话,那就得自己来创建了。这些类就是普通的Objective-C对象,能够存放任何信息。对象在执行时可以充分利用存于其中的信息,而且还可以随意调用定义在类中的方法。这就比派发队列中那些简单的块要强大许多。这些NSOperation类可以在代码中多次使用,他们符合软件开发中的“不重复”(Do’t Repeat Yourself,DRY)原则。
4.结论:
在解决多线程与任务管理问题时,GCD并非唯一方案,还可以考虑操作队列