如何并行共享RxJava Observable?

时间:2016-06-03 23:08:33

标签: rx-java

在下面的示例代码中,我正在尝试从远程source1和远程source2获取 - 这两者都需要来自远程source0的输入。我想从source0只取一次AND source from source1& source2同时。

$query = "SELECT firstname FROM users WHERE id = '17'";
$query_run = mysql_query($query);
$row = mysql_fetch_row($query_run);
echo $row[0]; 

此输出显示Source1和Source2未并行获取:

public class TestReactiveX5 {
  public static void main(String[] args) throws Exception {
    Scheduler scheduler = Schedulers.io();
    RemoteSourceData<Integer, Integer> source0 = new RemoteSource0();
    RemoteSourceData<Integer, String> source1 = new RemoteSource1();
    RemoteSourceData<Integer, String> source2 = new RemoteSource2();

    Observable<Integer> i = Observable.just(1);
    Observable<Integer> i0 = i.map(input -> source0.getData(input)).share();
    Observable<String> fooSource = i0.map(input0 -> source1.getData(input0)).subscribeOn(scheduler);
    Observable<String> barSource = i0.map(input0 -> source2.getData(input0)).subscribeOn(scheduler);

    Observable<List<String>> merged = Observable.merge(fooSource, barSource).toList();
    merged.subscribe(val -> System.out.println(val));

    Thread.sleep(15000);
  }

  @FunctionalInterface
  private static interface RemoteSourceData<IN, OUT> {
    public OUT getData(IN input);
  }

  public static class RemoteSource0 implements RemoteSourceData<Integer, Integer> {
    @Override
    public Integer getData(Integer input) {
      try {
        System.out.println("fetch from remote Source0 " + new Timestamp(System.currentTimeMillis()));
        Thread.sleep(2000L);
      } catch (InterruptedException ex) {
        // ignore
      }
      return 0;
    }
  }

  private static class RemoteSource1 implements RemoteSourceData<Integer, String> {
    @Override
    public String getData(Integer i) {
      try {
        System.out.println("fetch from remote Source1 " + new Timestamp(System.currentTimeMillis()));
        Thread.sleep(4000L);
      } catch (InterruptedException ex) {
        // ignore
      }
      return "foo";
    }
  }

  private static class RemoteSource2 implements RemoteSourceData<Integer, String> {
    @Override
    public String getData(Integer i) {
      try {
        System.out.println("fetch from remote Source2 " + new Timestamp(System.currentTimeMillis()));
        Thread.sleep(4000L);
      } catch (InterruptedException ex) {
        // ignore
      }
      return "bar";
    }
  }
}

如果删除share(),则Source1和Source2并行获取,但需要两次调用Source0:

fetch from remote Source0 2016-06-03 16:00:38.802
fetch from remote Source2 2016-06-03 16:00:40.803
fetch from remote Source1 2016-06-03 16:00:44.804
[bar, foo]

如何调用Source0和并行调用Source1&amp;源2?

1 个答案:

答案 0 :(得分:0)

并没有并行查询源,因为它们使用相同的线程,您可以在不同来源的操作之间进行休眠。

我添加了一些额外的日志记录来显示基本示例的执行线程:

  

从远程获取Source0 2016-06-03 23:28:35.426 Thread = Thread [RxIoScheduler-2,5,main]   从远程Source1获取2016-06-03 23:28:37.426 Thread = Thread [RxIoScheduler-2,5,main]   从远程获取Source2 2016-06-03 23:28:41.426 Thread = Thread [RxIoScheduler-2,5,main]   [foo,bar]

正如您所看到的,对于预期会睡2秒和4秒的所有任务来说,它是相同的线程。

我尝试了subscribeOnobserveOn的不同配置,并且不能说它对我来说是完全透明的,为什么RxJava在某些情况下会做它的功能,但这里有一些东西,为我工作:

public static void main(String[] args) throws Exception {
  Scheduler scheduler = Schedulers.io();
  RemoteSourceData<Integer, Integer> source0 = new RemoteSource0();
  RemoteSourceData<Integer, String> source1 = new RemoteSource1();
  RemoteSourceData<Integer, String> source2 = new RemoteSource2();

  Observable<Integer> i = Observable.just(1).subscribeOn(scheduler);
  Observable<Integer> i0 = i.map(source0::getData).share();
  Observable<String> fooSource = i0.observeOn(scheduler).map(source1::getData);
  Observable<String> barSource = i0.observeOn(scheduler).map(source2::getData);

  Observable<List<String>> merged = Observable.merge(fooSource, barSource).toList();
  merged.subscribe(System.out::println);

  Thread.sleep(15000);
}

输出:

  

从远程获取Source0 2016-06-03 23:37:11.264 Thread = Thread [RxIoScheduler-3,5,main]   从远程Source1获取2016-06-03 23:37:13.265 Thread = Thread [RxIoScheduler-2,5,main]   从远程Source2获取2016-06-03 23:37:13.265 Thread = Thread [RxIoScheduler-4,5,main]   [foo,bar]

现在fooSourcebarSource各有专用线程并且并行运行。