调度者(Schedulers)

优质
小牛编辑
130浏览
2023-12-01

调度者抽象了执行工作的机制。

执行工作不同的机制包括同线程,派遣队列,操作队列,创建线程,线程池,运行循环等

调度者有两个主要的操作。observeOnsubscribeOn

如果你想要在不同的调度者上执行工作,只需要调用 observeOn(scheduler) 操作符。

你将经常使用 observeOn 大大多于使用 subscribeOn

假如 observeOn 没有显示指定, 那幺任务将被执行在生成元素的调度器或线程上。

使用 observeOn 操作符的例子

  1. sequence1
  2. .observeOn(backgroundScheduler)
  3. .map { n in
  4. print("This is performed on background scheduler")
  5. }
  6. .observeOn(MainScheduler.instance)
  7. .map { n in
  8. print("This is performed on main scheduler")
  9. }

如果你需要开始序列生成( subscribe 方法)并且调用处置方法在特定的调度器上,使用 subscribeOn(scheduler)

如果 subscribeOn 没有显示指定,subscribe 方法会被调用在执行 subscribeNext or subscribe 的同一个线程或者调度器上。

如果 subscribeOn 没有显示指定,dispose 方法会被调用在执行初始化处置(disposing)的线程和调度器上。

简而言之,如果没有显示的调度器被选择,那些方法会被调用在相同的线程或调度器上。

串行和并发调度器

由于调度器真的能够成为任何东西,并且所有改变序列的操作符需要保留格外的隐性惯例, 你创建什幺类型的调度器是非常重要的。

假如调度器是并发的,Rx的 observeOnsubscribeOn 操作符将会确保所有工作正常。

如果你使用一些Rx能保证串行的调度器,这能执行额外的优化。

迄今为止只对派遣队列调度器实行了那些优化。

串行派遣队列调度器仅仅使用 dispatch_async 调用来优化 observeOn

自定义调度器

除了当前的调度器意外,你可以写属于自己的调度器。

如果你想要描述立刻执行工作的调度器,你可以通过实现 ImmediateScheduler 协议创建属于自己的调度器。

  1. public protocol ImmediateScheduler {
  2. func schedule<StateType>(state: StateType, action: (/*ImmediateScheduler,*/ StateType) -> RxResult<Disposable>) -> RxResult<Disposable>
  3. }

如果你想创建新的支持基于时间操作的调度器,然后你需要实现。

  1. public protocol Scheduler: ImmediateScheduler {
  2. associatedtype TimeInterval
  3. associatedtype Time
  4. var now : Time {
  5. get
  6. }
  7. func scheduleRelative<StateType>(state: StateType, dueTime: TimeInterval, action: (StateType) -> RxResult<Disposable>) -> RxResult<Disposable>
  8. }

假如调度器只有周期性调度的能力,你可以通过实现 Rx 的 PeriodicScheduler 协议。

  1. public protocol PeriodicScheduler : Scheduler {
  2. func schedulePeriodic<StateType>(state: StateType, startAfter: TimeInterval, period: TimeInterval, action: (StateType) -> StateType) -> RxResult<Disposable>
  3. }

假如调度器不支持 PeriodicScheduling 的能力,Rx 将会不给察觉的模拟周期性调度。

内置调度器

Rx 可以使用所有类型的调度器,但是它还能执行一些额外的优化,如果他能证明调度器是串行的。

这些是当前支持的调度器

当前线程调度器(CurrentThreadScheduler)串行调度器

工作的调度器单位在当前线程上。
这是生成元素操作的默认调度器。

这个调度器有时候也被称为 蹦床调度器

如果 CurrentThreadScheduler.instance.schedule(state) { } 首次被调用在同一个线程上,调度的行为会被立刻执行,并且隐藏的队列会被创建,所有递归调度操作将暂时入队。

如果一些父结构在调用堆上已经正在执行 CurrentThreadScheduler.instance.schedule(state) { },调度行为将会被入队并且执行,在当前运行行为的时候,并且所有先前的入队行为已经完成执行。

主调度器(MainScheduler)(串行调度器)

抽象工作需要被执行在 MainThread。假如 schedule 方法被调用在主线程,他就会直接执行动作不再调度。

这个调度器经常被用在执行 UI 任务。

串行派遣队列调度器(SerialDispatchQueueScheduler)(串行调度)

抽象工作需要在指定的 dispatch_queue_t 上被执行。他会确认即使派遣队列被同时传递,他也将变换成一个串行(线性)的。

串行调度器允许为了 observeOn 确定的优化。

主调度器是一个 SerialDispatchQueueScheduler 的实例。

并行调度器队列调度器(ConcurrentDispatchQueueScheduler)(并发调度器)

抽象工作需要被执行在指定的 dispatch_queue_t 上。你还可以传递一个串行派遣队列,他不应该引起任务问题。

这个调度器适合在当一些任务需要被执行在后台。

操作队列调度器(OperationQueueScheduler)(并发调度器)

抽象工作需要被执行在指定的 NSOperationQueue 上。

这个调度器适合在有一些很大的块工作需要被执行在后台,并且你需要使用 maxConcurrentOperationCount 微调并发处理。