Task order for Observable.combineLatest and Schedulers.computation()
See original GitHub issueVersion: 1.3.0
Hello!
I have observed strange behavior while I was using combineLatest with Schedulers.computation(). Please take a look at example:
private static void runSubscription(String prefix, boolean shouldWait, ConcurrentMap<String, Integer> stat) {
Observable<Long> interval = Observable.interval(1000, TimeUnit.MILLISECONDS);
Observable.combineLatest(Observable.just(prefix), interval, (s1, s2) -> s1)
.subscribeOn(Schedulers.computation())
.observeOn(Schedulers.computation())
.onBackpressureLatest()
.subscribe(s -> {
try {
if (shouldWait) {
Thread.sleep(4000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
stat.merge(s, 1, (v1, v2) -> v1 + v2);
});
}
public static void main(String[] args) throws Exception {
ConcurrentMap<String, Integer> stat = new ConcurrentHashMap<>();
stat.put("1", 0);
runSubscription("1", true, stat);
for (int i = 1; i < Runtime.getRuntime().availableProcessors(); i++) {
String key = String.valueOf(i + 1);
stat.put(key, 0);
runSubscription(key, false, stat);
}
while (!Thread.currentThread().isInterrupted()) {
// Print invocation statistics
System.out.println(stat);
Thread.sleep(4000);
}
}
The output shows how many times particular subscriber was invoked. First column - subscriber number, second - invocation count. For version above output is:
{1=0, 2=0, 3=0, 4=0}
{1=0, 2=1, 3=1, 4=3}
{1=1, 2=1, 3=1, 4=7}
{1=2, 2=1, 3=1, 4=11}
{1=3, 2=1, 3=1, 4=15}
{1=4, 2=1, 3=1, 4=19}
{1=5, 2=1, 3=1, 4=23}
{1=6, 2=1, 3=1, 4=27}
{1=7, 2=1, 3=1, 4=31}
...
The output is not stable, but every time some of threads invoked less times.
But when I changed both Schedulers.computation()
to Schedulers.io()
, output changed to expected:
{1=0, 2=0, 3=0, 4=0}
{1=0, 2=3, 3=3, 4=3}
{1=1, 2=7, 3=7, 4=7}
{1=2, 2=11, 3=11, 4=11}
{1=3, 2=15, 3=15, 4=15}
{1=4, 2=19, 3=19, 4=19}
Is it incorrect usage of scheduler, or it is a bug?
Issue Analytics
- State:
- Created 6 years ago
- Comments:7 (3 by maintainers)
Top Results From Across the Web
java - Unit test of RxJava combineLatest hangs when single thread ...
This testcase hangs when executed. If I remove the scheduler hook, it runs fine. Any idea why this is case and how can...
Read more >RxJava Combining Operators - Kodeco
In this tutorial, you'll use RxJava combining operators to merge, filter and transform your data into succinct and reusable streams.
Read more >Advanced RxJava programming with stream nesting - Medium
When we schedule a periodic job on the worker, it requires a callback Runnable to call the run() method each time a period...
Read more >Primer on RxJS Schedulers - André Staltz
Schedulers in RxJS are things that control the order of event ... combineLatest(a$, b$, (a, b) => a + b); c$.subscribe(c => console.log(c));....
Read more >Exploring RxJava in Android
An onNext() method that the Observable calls whenever it wishes to publish a ... Schedulers.computation() this gives us a Scheduler that is ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
The
computation
scheduler has a number of worker threads that is, by default, is equal to the number of available processors and hands out worker threads in a round robin fashion. Since there is a limited number of them and you block one of them in your first run, the subsequent runs will likely get that scheduler and block tasks behind it.You are practically wasting schedulers as
subscribeOn
in this case has no effect,interval
already runs on the computation scheduler andobserveOn
moves the events from one computation worker to another without much benefit.OK, thanks for explanation.