NSOperation 是 OC 语言中基于 GCD 的面向对象的封装
NSOperation 与 GCD 的区别
NSOperation 与 NSOperationQueue
NSOperation
需要和 NSOperationQueue
配合使用来实现多线程方案。单独使用 NSOperation 的话, 它是属于同步操作, 并不具备开启新线程的能力。
NSOperation:操作
- NSOperation 类是一个抽象类,不能直接使用它来封装任务,而是使用系统定义的子类( NSInvocationOperation 或 NSBlockOperation)或者自定义子类来封装任务。
- 操作对象是一个单发对象,即它只执行一次任务,不能再次执行。通常通过将操作添加到操作队列来执行操作。
NSOperationQueue:队列
获取主队列:[NSOperationQueue mainQueue]
获取当前队列:[NSOperationQueue currentQueue]
NSOperation 使用
如果不想使用 NSOperationQueue,可以通过调用 NSOperation 对象的start方法来自己执行操作。默认情况下,调用 NSOperation 的 start 方法并不会开一条新线程去执行操作,而是在当前线程同步执行操作。
注意点:如果将操作添加到队列后,又调用 start 方法,会导致Crash
1 | - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { |
- 模拟图片下载完成后回到主线程更新 UI:
1 | NSOperationQueue *queue = [[NSOperationQueue alloc]init]; |
NSOperation进阶
什么是并发数?
并发数就是同时执行的任务数。
比如,同时开3个线程执行3个任务,并发数就是3。
但是,并发数是3,并不代表开启的线程数就是3,也有可能是4个或者5个。因为线程有可能在等待,进入了就绪状态。
@property NSInteger maxConcurrentOperationCount;
NSOperation 与 GCD 区别:
GCD 会自动重用线程,而 NSOperation 不会,会一直开线程。
而开太多线程反而会影响效率,我们需要自己控制,一般开 3-6 个。
队列的暂停/继续/取消操作
1 | /* |
1 | - (IBAction)start:(id)sender { |
操作执行状态控制
操作的执行状态:
1 | @property (readonly, getter=isReady) BOOL ready; //就绪 |
怎么控制 NSOperation 的状态?
如果只重写了main方法,底层控制变更操作执行完成状态,以及操作退出;
如果重写了start方法,自行控制任务状态。
系统是怎样移除一个isFinished = YES的 NSOperation 的?
通过KVO。