RxJava - “Only one emission is allowed to travel up the Observable chain at a time…”

我们两清 提交于 2020-01-04 09:48:17

问题


I'm reading a blog post here: http://tomstechnicalblog.blogspot.com/2016/02/rxjava-understanding-observeon-and.html

where it is said that

No matter what Scheduler you are subscribed on, only one emission is allowed to travel up the Observable chain of operators at a time. Below, you can observe that the emission must be pushed all the way from the source to the Subscriber before the next emission can start.

Right above that quoted text is an example written as:

 public static void main(String[] args) {

    Observable<Integer> source = Observable.range(1,10);

    source.map(i -> i * 100)
            .doOnNext(i -> System.out.println("Emitting " + i
                    + " on thread " + Thread.currentThread().getName()))
            .observeOn(Schedulers.computation())
            .map(i -> i * 10)
            .subscribe(i -> System.out.println("Received " + i + " on thread "
                    + Thread.currentThread().getName()));

    sleep(3000);
}

with the output as: (ref output1)

Emitting 100 on thread main
Emitting 200 on thread main
Emitting 300 on thread main
Emitting 400 on thread main
Emitting 500 on thread main
Emitting 600 on thread main
Emitting 700 on thread main
Emitting 800 on thread main
Emitting 900 on thread main
Emitting 1000 on thread main
Received 1000 on thread RxComputationThreadPool-3
Received 2000 on thread RxComputationThreadPool-3
Received 3000 on thread RxComputationThreadPool-3
Received 4000 on thread RxComputationThreadPool-3
Received 5000 on thread RxComputationThreadPool-3
Received 6000 on thread RxComputationThreadPool-3
Received 7000 on thread RxComputationThreadPool-3
Received 8000 on thread RxComputationThreadPool-3
Received 9000 on thread RxComputationThreadPool-3
Received 10000 on thread RxComputationThreadPool-3

Initially, I thought the end result would look like: (ref output2)

Emitting 100 on thread main
Received 1000 on thread RxComputationThreadPool-3
Emitting 200 on thread main
Received 2000 on thread RxComputationThreadPool-3
Emitting 300 on thread main
Received 3000 on thread RxComputationThreadPool-3
Emitting 400 on thread main
Received 4000 on thread RxComputationThreadPool-3
Emitting 500 on thread main
Received 5000 on thread RxComputationThreadPool-3
Emitting 600 on thread main
Received 6000 on thread RxComputationThreadPool-3
Emitting 700 on thread main
Received 7000 on thread RxComputationThreadPool-3
Emitting 800 on thread main
Received 8000 on thread RxComputationThreadPool-3
Emitting 900 on thread main
Received 9000 on thread RxComputationThreadPool-3
Emitting 1000 on thread main
Received 10000 on thread RxComputationThreadPool-3

but I can see that calling observeOn allows one stream to handoff to another so that it can keep going. So in the example, it seems like the intial map and doOnNext all complete before the second map and subscribe.

Question:


Is it correct to say that theoretically, the output could look like "ref output2" or would it always look identical to "ref output1"?

Again, my reasoning for this is that it seems that one operator has to process all of the observables completely before it gets handed off to the next operator with the example above.


回答1:


In theory, both ref output1 and ref output2 are possible but in practice, it will be closer to ref output1. Depending on how hot Schedulers.computation() becomes, you may see some interleaving but it is unlikely you get a perfect ping-pong pattern.

What happens is that observeOn has a prefetch of 128 elements and the first element received will trigger an asynchronous re-emission of elements in an internal queue. Since Threads in executors often don't start/resume quickly enough, the time the re-emission starts the main thread has already emitted all of its values.

You can get the ping-pong effect by configuring observeOn to have a prefetch value of 1 via an overload. However, in this case the original emission may get dragged to the re-emission thread instead of staying on the original thread and you also have to introduce subscribeOn after range to make sure the first doOnNext stays on its own thread. (Also note that you can't pin execution with standard schedulers to the main thread, you need a blocking scheduler for that.)



来源:https://stackoverflow.com/questions/44914509/rxjava-only-one-emission-is-allowed-to-travel-up-the-observable-chain-at-a-ti

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!