RxJava的整个流程分为三个步骤 

  1. 从上到下创建任务链,这里没有涉及线程调度。默认执行在当前线程,在这里也就是主线程
  2. 自下向上逆向订阅,这个过程subscribeOn起作用,observeOn不起切换线程作用。
  3. 从上到下执行,类似map中的代码,这时候observeOn起切换线程作用。

rxjava 默认线程大小 rxjava是怎么实现线程切换的_rxjava

也是为什么subscribeOn只有第一次起作用,observeOn每次都起作用。 

Q1:为什么 subscribeOn() 只有第一次切换有效

简单分析一下代码执行流程

  1. 从上到下,建立上下依赖关系,初始化线程
  2. .subscribe为调用起点,自下向上开始准备调用,这个过程subscribeOn起作用,observeOn不起切换线程作用。
  3. 从上到下执行,类似map中的代码,这时候observeOn起切换线程作用。

因为 RxJava 最终能影响 ObservableOnSubscribe 这个匿名实现接口的运行环境的只能是最后一次运行的 subscribeOn() ,又因为 RxJava 订阅的时候是从下往上订阅,所以从上往下第一个 subscribeOn() 就是最后运行的,这就造成了写多个 subscribeOn() 只有第一个subscribeOn()有用。
如下图:subscribeOn()产生的线程切换发生在代码执行的第二层,而它的回溯又将会执行在新的线程中。因此,在subscribeOn切换线程以后的流程,均将在新的线程中执行。

observeOn()产生的线程切换都发生在第三层执行层,而在切换线程前的业务代码由于已经执行了,故不受切换线程切换的影响。

rxjava 默认线程大小 rxjava是怎么实现线程切换的_rxjava_02

 Q2:每一次observeOn的使用,都会将后面的观察者(同上)和将要切换的线程内容封装起来。

每次observeOn都会切换后面内容的执行线程。

Q3:observeOn() 的线程切换原理

总结:

  1. 子线程切换主线程:给主线程所在的Handler发消息,然后就把逻辑切换过去了。
  2. 主线程切换子线程:把任务放到线程池中执行就能把执行逻辑切换到子线程
  3. 子线程切换子线程:把任务分别扔进两个线程就行了。

Q4:线程控制Scheduler

可以利用 subscribeOn() 结合 observeOn() 来实现线程控制,让事件的产生和消费发生在不同的线程。又知道map(),和flatMap()等可以做不同的变换,那么也可以通过多次地调用函数来实现多次线程的切换

Observable.just(1, 2, 3, 4) // IO 线程,由 subscribeOn() 指定
    .subscribeOn(Schedulers.io())
    .observeOn(Schedulers.newThread())
    .map(mapOperator) // 新线程,由 observeOn() 指定
    .observeOn(Schedulers.io())
    .map(mapOperator2) // IO 线程,由 observeOn() 指定
    .observeOn(AndroidSchedulers.mainThread) 
    .subscribe(subscriber);  // Android 主线程,由 observeOn() 指定