Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
RxJava:subscribeOn和observeOn未按预期工作_Java_Rx Java_Reactivex - Fatal编程技术网

RxJava:subscribeOn和observeOn未按预期工作

RxJava:subscribeOn和observeOn未按预期工作,java,rx-java,reactivex,Java,Rx Java,Reactivex,也许我只是真正理解了subscribeOn和observeOn的内部工作原理,但我最近遇到了一些非常奇怪的事情。我的印象是,subscribeOn决定了调度器最初开始处理的位置(特别是当我们有很多maps改变数据流时),然后observeOn可以在这些map之间的任何地方使用,在适当的时候改变调度器(先联网,然后计算,最后更改UI线程) 但是,我注意到,如果不将这些调用直接链接到我的Observable或Single,它将无法工作。下面是一个JUnit测试的最小工作示例: import org.

也许我只是真正理解了
subscribeOn
observeOn
的内部工作原理,但我最近遇到了一些非常奇怪的事情。我的印象是,
subscribeOn
决定了调度器最初开始处理的位置(特别是当我们有很多
map
s改变数据流时),然后
observeOn
可以在这些
map
之间的任何地方使用,在适当的时候改变调度器(先联网,然后计算,最后更改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);
  }
}
按预期工作()
给了我

Doing some computation on thread RxComputationScheduler-1
Doing test on thread main
Observing on thread RxIoScheduler-2
唯一的区别是,在第一次测试中,在创建单之后,有一个分号,然后才应用调度程序,在工作示例中,方法调用直接链接到单的创建。但这难道不应该是无关的吗?

所有“修改”运算符执行的操作是不可变的,这意味着它们返回一个新的流,该流以与前一个流不同的方式接收通知。由于您刚刚调用了
subscribeOn
observeOn
运算符,并且没有存储它们的结果,因此以后进行的订阅位于未更改的流上


一方面注意:我不太理解您对
subscribeOn
行为的定义。如果您是说映射运算符受到它的影响,那就不是这样了。
subscribeOn
定义了一个调度程序,在该调度程序上调用OnSubscribe函数。在您的例子中,传递给
create()的函数
方法。另一方面,
observeOn
定义了每个连续流(由应用的操作员返回的流)处理来自上游的排放的调度程序。

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

这是一个非常常见的错误。每个操作符返回一个新对象,您应该进一步链接。您只需应用subscribeOn+observeOn,忽略返回的单条并订阅原始未更改的源。
Doing some computation on thread RxComputationScheduler-1
Doing test on thread main
Observing on thread RxIoScheduler-2