3

I tried below.

public static void main(String[] args) throws Exception {
  Observable.interval(100L, TimeUnit.MILLISECONDS)
    .onBackpressureDrop().subscribe(new Subscriber<Long>() {

    @Override
    public void onStart() {
      request(1L);
    }

    @Override
    public void onNext(Long t) {
      System.out.println("received: " + t);
      try {
        Thread.sleep(1000L);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      request(1);
    }

    @Override
    public void onCompleted() {
      System.out.println("onCompleted");
    }

    @Override
    public void onError(Throwable e) {
      e.printStackTrace();
    }
  });

  TimeUnit.SECONDS.sleep(10L);
}

I expected that the subscriber would receive the item 0, 10, 20, 30... because onBackpressureDrop method would drop the items before the request. But the result was 0, 1, 2, 3....

Also, I tried onBackpressureLatest() but the result was the same, 0, 1, 2, 3....

This seem to me the same as onBackpressureBuffer.

Do I misunderstand this method? If so, how I tried that onBackpressureDrop method would work as the marble diagram in Javadoc?

Mark Gilchrist
  • 1,972
  • 3
  • 24
  • 44
otal
  • 391
  • 2
  • 15

2 Answers2

2

That happens because you put thread on which interval() is operating to sleep. One possible solution - adding observeOn(Scheduler,bufferSize) operator:

  Observable.interval(100L, TimeUnit.MILLISECONDS)
            .onBackpressureDrop()
            .observeOn(Schedulers.io(), 1)
            .subscribe(new Subscriber<Long>() {

                @Override
                public void onStart() {
                    request(1L);
                }

                @Override
                public void onNext(Long t) {
                    System.out.println("received: " + t);
                    try {
                        Thread.sleep(1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    request(1);
                }

                @Override
                public void onCompleted() {
                    System.out.println("onCompleted");
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                }
            });

    Observable.empty().delay(1, TimeUnit.MINUTES).toBlocking().subscribe();

That way your subscriber operates on io() scheduler with minimal buffer size, and backpressure seems to work:

received: 0
received: 11
received: 22

m.ostroverkhov
  • 1,910
  • 1
  • 15
  • 17
  • I tried and I got what I want. Thank you for your help! Also, I noticed that if I put bufferSize in `observeOn`, I don't have to call `request` in Subscriber. It looks like that `observeOn` method with buffer size would call Subscriber's `request` method inside. – otal May 19 '16 at 01:27
2

onBackpressureDrop doesn't do anything here because in this particular case there is no 'backpressure'. What you do in the subscribe method is block the thread on which new values are created by the Observable.interval method by sleeping for 1 second after each emission. Therefore the Observable.interval does not generate a value every 100 milliseconds but is forced to do this only once per second!

I suggest you to put an observeOn between the onBackpressureDrop and subscribe such that generating of values and the things you do in the subscribe are on different threads. To see the effect, use this overload with a small buffer size (eg. 1). Any kind of Scheduler will do as far as I know.

RvanHeest
  • 869
  • 6
  • 12
  • I tired and I got what I want. So, the problem is that I also blocked the emission. Now, I understand. Thank you very much. – otal May 19 '16 at 01:18