什么是scheduler?
在开始使用scheduler之前,首先要明白他是什么。
总的来说,scheduler是一个任务执行的上下文。这个上下文可能是一个thread、dispatchqueue、OperationQueue等。
一个常见的误解是:scheduler等价于线程。但实际并不是这样 。如果你自定义一个scheduler(虽然并不推荐自定义),你可以创建多个scheduler共用一个线程,或者一个scheduler构建在多个线程上(虽然比较奇怪,但确实可以)。
总之,scheduler并不是线程,他和线程并没有一对一的关系。
关于scheduler的两个操作符
Rx最重要的能力之一就是能够在任何时间切换scheduler。
subscribeOn
有时你希望改变 observable 生成element的代码的执行上下文环境( 比如:对于Observable.create{ … },就是闭包中的那段代码 )。这个时候就可以使用subscribeOn操作符。
observeOn
如果你希望改变subscribe函数执行的上下文,那么你可以使用observeOn操作符。
Hot and Cold Observable
一个Observable什么时候开始发送他的elements呢?这取决于Observable。一个“Hot Observable”会在他创建完成后就开始emit elements,这样之后subscribe他的observer就能够在中间开始接收elements。一个“Cold Observable”会等到有Observer subscribe他时才开始emit elements,这样就保证了observer能够收到从头开始的所有elements。
Hot Observales | ColdObservables |
---|---|
都是sequence | 都是sequence |
不管有没有Observer subscribe他,都会使用资源 | 不会使用资源,直到有Observer subscribe他。 |
Variables / properties / constants, tap coordinates, mouse coordinates, UI control values, current time | Async operations, HTTP Connections, TCP connections, streams |
通常包含N个element | 通常包含1个element |
不管有没有observer subscribe他都会产生sequence element | 有observer subscribe他才产生sequence elements。 |
sequence的计算资源通常是所有observer共享的 | sequence的计算资源通常是每个Observer分配一份 |
通常都是有状态的 | 通常都是无状态的 |
陷阱
对于cold observable我们确实可以通过subscibeOn操作符来控制element在哪个线程上产生,因为他是在subscribe时才去生成elements的。但是对于一些Hot Observable,如果你想通过subscibeOn去切换scheduler,你会发现并不起作用,因为elements的生成在Observable创建时就会生成,之后我们就不能控制他的scheduler。
内置的scheduler
CurrentThreadScheduler
抽象了在当前线程上执行的任务。如果你没有执行scheduler,那么这个就是默认的scheduler。
SerialDispatchQueueScheduler
抽象了某个需要在 serial DispatchQueue上执行某个任务。他能够保证即使你传入的是一个Concurrent queue,他也会把他转化成serial。
非常重要的一点是这个scheduler是serial的,因为某些操作符会根据这个进行优化。
因为不能够检测到传入的是concurrent的还是serial的,所以在内部都会创建一个serail queue,然后所有的任务都是在这个内部的serail queue上执行。
MainScheduler
抽象了在主线程上执行任务,这个scheduler通常用于执行某些UI操作。继承自SerialDispatchQueueScheduler。这个scheduler对ObserveOn操作符有优化,所以如果你想要subscribe函数在主线程上执行,那么用MainScheduler。另外还有一个ConcurrentMainScheduler,这个scheduler对subscibeOn操作符有优化,所以,你如果希望element的产生在主线程上,那么用ConcurrentMainScheduler。
ConcurrentDispatchQueueScheduler
抽象了在某个concurrent dispatchqueue上执行的任务。这个scheduler通常用于某些需要在后台执行的任务。
OperationQueueScheduler
抽象了在某个OperationQueue上执行的任务。这个sechulder适合当你想要控制并发数量时用。