RX Java 2 contract on sequential processing

Mikha :

TL; DR - is it guaranteed that by default, only one thread is ever used in any given time when observing events emitted by Observable?

It seems to me that RxJava2 is generally sequential unless expressed otherwise via things like parallel(). Even with observeOn/subscribeOn, I see that there are e.g. never two threads running simultaneously for doOnNext():

AtomicInteger counter = new AtomicInteger();

PublishSubject<Integer> testSubject = PublishSubject.create();

testSubject
.observeOn(Schedulers.io())
.doOnNext(val -> {
  if(counter.incrementAndGet() > 1)
    System.out.println("Whoa!!!!"); // <- never happens

  Thread.sleep(20);

  counter.decrementAndGet();
})
.subscribe();

for (int i = 0; i < 10000; i++) {
  Thread.sleep(10);
  testSubject.onNext(i);
}

No matter how I change this example - unless I go hardcore with .toFlowable(...).parallel().runOn(...), I don't see doOnNext running on different threads simultaneously.

I'd like to rely on this feature so I can ignore synchronisation issues in my operators, however I never saw it explicitly specified in the documentation for either RxJava2, RxJava1 or even just RX in general. Maybe I just missed it, could anyone pls point me to where this part of the contract is described?

Thanks!

zella :

From http://reactivex.io/documentation/contract.html

Observables must issue notifications to observers serially (not in parallel). They may issue these notifications from different threads, but there must be a formal happens-before relationship between the notifications.

In your example you are not breaks this observable contract. But if you implement Observable wrong, two threads will run simultaneously:

AtomicInteger counter = new AtomicInteger();

    Observable.create(emitter -> {
        new Thread(() -> {
            for (int i = 0; i < 10000; i++) {
                try {
                    Thread.sleep(1);
                    emitter.onNext(i);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
            }
        }).start();
        for (int i = 0; i < 10000; i++) {
            Thread.sleep(1);
            emitter.onNext(i);

        }
    }).doOnNext(integer -> {
        if (counter.incrementAndGet() > 1)
            System.out.println("Whoaa!");
        counter.decrementAndGet();
        Thread.sleep(1);

    }).subscribe();

Seems you can fix this behavior with observeOn https://github.com/ReactiveX/RxJava/issues/5550#issuecomment-325114185

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=154666&siteId=1