0

I'm consuming event using from different external sources/subscription wrap to different Flowable. The source doesn't matter as I could reproduce the issue with a simple loop. I have :

  • Different FlowableEmitter (3 is enough to reproduce)
  • Single Thread for the emitter (below is the main thread)
  • Single Thread for subscriber (newSingleThreadExecutor)

This a simple code the reproduce

    final ExecutorService executor = Executors.newSingleThreadExecutor();
    final Scheduler scheduler = Schedulers.from(executor);

    List<FlowableEmitter<Long>> emitterList = new ArrayList<>();
    for (int i=0; i<3; ++i) {
        final int finalI = i;
        Flowable.create( new FlowableOnSubscribe<Long>(){
            @Override
            public void subscribe(FlowableEmitter<Long> emitter) {
                emitterList.add(emitter);
            }
        },  BackpressureStrategy.MISSING)
                .observeOn(scheduler)
                .subscribe(
                        val -> System.out.println(
                            "[" +Thread.currentThread().getName()
                            + "] Flow:" + finalI 
                            + " > " + Long.toString(val)));
    }

    long state = 0;
    for (int i=0; i<5; ++i) {
        for (FlowableEmitter<Long> emitter: emitterList){
            emitter.onNext(++state);
        }
    }

    executor.shutdown();

My problem is that the events are not consumed on the same order as they are emitted. if I remove the observeOn(scheduler) it's working fine, but I need to emitter and subscriber on different threads. I have also tested different BackpressureStrategy and it doesn't help.
Any clue to have all number subscribed/printed in order (1,2,3,4,5...14,15) instead of what I have below

[pool-1-thread-1] Flow:0 > 1
[pool-1-thread-1] Flow:0 > 4
[pool-1-thread-1] Flow:0 > 7
[pool-1-thread-1] Flow:0 > 10
[pool-1-thread-1] Flow:0 > 13
[pool-1-thread-1] Flow:1 > 2
[pool-1-thread-1] Flow:1 > 5
[pool-1-thread-1] Flow:1 > 8
[pool-1-thread-1] Flow:1 > 11
[pool-1-thread-1] Flow:1 > 14
[pool-1-thread-1] Flow:2 > 3
[pool-1-thread-1] Flow:2 > 6
[pool-1-thread-1] Flow:2 > 9
[pool-1-thread-1] Flow:2 > 12
[pool-1-thread-1] Flow:2 > 15

I'm using rx-java 2.2.5 and Java 8 if that matter.

Rod1677
  • 23
  • 3

1 Answers1

0

observeOn is not fair and may hug the emission thread if there is more work to do. By round-robin emitting, one source may be ready to emit more and thus you don't get a perfect interleaving. Note also that by using MISSING strategy, you are prone to backpressure exceptions. Try requestObserveOn from the extensions project:

final ExecutorService executor = Executors.newSingleThreadExecutor();
final Scheduler scheduler = Schedulers.from(executor);

List<FlowableEmitter<Long>> emitterList = new ArrayList<>();
for (int i=0; i<3; ++i) {
    final int finalI = i;
    Flowable.create( new FlowableOnSubscribe<Long>(){
        @Override
        public void subscribe(FlowableEmitter<Long> emitter) {
            emitterList.add(emitter);
        }
    },  BackpressureStrategy.BUFFER)
            // ---------------------------------------------------------
            .compose(FlowableTransformers.requestObserveOn(scheduler))
            // ---------------------------------------------------------
            .subscribe(
                    val -> System.out.println(
                        "[" +Thread.currentThread().getName()
                        + "] Flow:" + finalI 
                        + " > " + Long.toString(val)));
}

long state = 0;
for (int i=0; i<5; ++i) {
    for (FlowableEmitter<Long> emitter: emitterList){
        emitter.onNext(++state);
    }
}

executor.shutdown();
akarnokd
  • 69,132
  • 14
  • 157
  • 192
  • Will he have any problems by never calling `.onComplete()` on any of his flowable emitters? – EpicPandaForce Mar 04 '19 at 15:16
  • 1
    Not in this particular scenario. – akarnokd Mar 04 '19 at 15:18
  • @akarnokd Thanks for clarifying the problem. Just tried FlowableTransformers.requestObserveOn but still getting the output mixed up (#1 is actually consumed after #15 in my first try) so not really better. – Rod1677 Mar 05 '19 at 00:03