如何计算和阻止在另一个线程上执行的Observable?

时间:2017-06-25 20:34:48

标签: java multithreading asynchronous rx-java rx-java2

我有一个基础RxJava 2 Observable我在主线程上运行。然后我调用observeOn在另一个线程上运行一些计算。然后我使用autoConnect订阅count和另一个副作用操作(写出计算结果)。在示例中,这显示为System.out.println,但假设这是一个可能需要一段时间的操作。我想避免计数完成时可能存在的竞争条件,但是在另一个线程上写出计算的最后一个元素的结果并没有完成。

为此,我在Future调用中创建了.count(),在副作用操作上调用blockingSubscribe,最后在未来调用.get() ,确保主线程块完成两个可观察操作。这里有更好的解决方案,以避免在编写最后一个元素时丢失吗?我是否甚至需要这样做,或者是否有一些保证Observables给我错过了?

值得注意的是,我希望避免重复计算Observable的初始元素,因为这可能在许多昂贵的步骤之后发生。

我的示例代码如下所示。

Stream<Integer> ints = ImmutableList.of(1, 2, 3, 4, 5, 6)
    .stream().map(i -> {
      System.out.println("emitting:" + i);
      return i;
    });

Observable<Integer> observable = Observable.fromIterable(() -> ints.iterator())
    .observeOn(Schedulers.computation())
    .map(x -> x + 1)
    .publish()
    .autoConnect(2);

Future<Long> count = observable.count().toFuture();
// pretend that instead of printing here, this operation
// could take some time to complete
observable.blockingSubscribe(i -> System.out.println("got " + i));
Long c = count.get();

return count;

1 个答案:

答案 0 :(得分:2)

而不是创建2个流,您可以在单个流中完成所有工作:

import {withRouter} from "react-router"; 

class MyComponent extends React.Component {
   ...
   changeRoute = () => {
        this.props.history.push('/dashboard)
   }
   ...
}


 export default withRouter(MyComponent);

使用副作用Observable<Integer> observable = Observable.fromIterable(() -> ints.iterator()) .observeOn(Schedulers.computation()) .map(x -> x + 1); observable.doOnNext(integer -> { //your heavy work here }) .count() .subscribe(aLong -> { //do something with the final count }); 进行繁重的计算,并在doOnNext()运算符后的订阅中使用最终计数执行某些操作。 这将保证您执行的顺序,通知永远不会同时发生,这是Observable合同的一部分,每个count()将按顺序发生,出于同样的原因,订户的最终doOnNext()将发生最后,由于onNext()运算符基于源count()Observable通知)的完成,因此将在onComplete处发出并处理所有项目后发生。