RxJava:subscribeOn和observeOn没有按预期工作

时间:2017-01-22 09:24:36

标签: java rx-java reactivex

也许我真的了解subscribeOnobserveOn的内部运作方式,但最近我遇到了一些非常奇怪的事情。我的印象是,subscribeOn确定调度程序最初开始处理的位置(特别是当我们有很多map更改数据流时),然后observeOn可以在maps之间的任何地方使用,以在适当时更改调度程序(首先进行网络连接,然后计算,最后更改UI线程)。

但是,我注意到,当没有直接将这些调用链接到我的Observable或Single时,它将无效。这是一个最小的工作示例JUnit测试:

import org.junit.Test;
import rx.Single;
import rx.schedulers.Schedulers;

public class SubscribeOnTest {

  @Test public void not_working_as_expected() throws Exception {
    Single<Integer> single = Single.<Integer>create(singleSubscriber -> {
      System.out.println("Doing some computation on thread " + Thread.currentThread().getName());
      int i = 1;
      singleSubscriber.onSuccess(i);
    });
    single.subscribeOn(Schedulers.computation()).observeOn(Schedulers.io());

    single.subscribe(integer -> {
      System.out.println("Observing on thread " + Thread.currentThread().getName());
    });
    System.out.println("Doing test on thread " + Thread.currentThread().getName());
    Thread.sleep(1000);
  }

  @Test public void working_as_expected() throws Exception {
    Single<Integer> single = Single.<Integer>create(singleSubscriber -> {
      System.out.println("Doing some computation on thread " + Thread.currentThread().getName());
      int i = 1;
      singleSubscriber.onSuccess(i);
    }).subscribeOn(Schedulers.computation()).observeOn(Schedulers.io());

    single.subscribe(integer -> {
      System.out.println("Observing on thread " + Thread.currentThread().getName());
    });
    System.out.println("Doing test on thread " + Thread.currentThread().getName());
    Thread.sleep(1000);
  }
}

测试not_working_as_expected()为我提供了以下输出

Doing some computation on thread main
Observing on thread main
Doing test on thread main

working_as_expected()给了我

Doing some computation on thread RxComputationScheduler-1
Doing test on thread main
Observing on thread RxIoScheduler-2

唯一的区别是,在第一个测试中,在创建单个元素之后有一个分号,然后才应用调度程序,并且在工作示例中,方法调用直接链接到Single的创建。但这不应该是无关紧要的吗?

2 个答案:

答案 0 :(得分:3)

运营商执行的所有“修改”都是 不可变 ,这意味着它们会返回一个新流,该流以前一个方式更改的方式接收通知。由于您刚刚调用subscribeOnobserveOn运算符而未存储其结果,因此稍后进行的订阅将在未更改的流上进行。

一方注意:我不太了解您对subscribeOn行为的定义。如果你的意思是地图运算符受某种程度的影响,那就不是这样了。 subscribeOn定义了一个调度程序,在其上调用OnSubscribe函数。在您的情况下,您传递给create()方法的函数。另一方面,observeOn定义调度程序,每个连续流(应用运算符返回的流)处理来自上游的排放。

答案 1 :(得分:2)

.subscribeOn(*) - 返回Observable的新实例,但在第一次测试中,您只需忽略它,然后订阅原始Observable,这显然默认订阅默认主线程。