RxJava2.0 (6) back pressure strategy Flowable

In the previous section, we learned Observablehow to solve the problem of unbalanced flow velocity between upstream and downstream. The reason for learning this is that Observablethere are still many scenarios where it is used. Some friends Flowablefeel that Flowableit can solve any problem after hearing about it, and even some Abandoning Observablethis kind of thinking, it is absolutely impossible, they all have their own advantages and disadvantages.

In this section, let's learn how to use it first Flowable. It has a lot of things, it's cumbersome, and it's more troublesome to explain, but I'll try to use 通俗易懂words to make it clear. After all, this is a 通俗易懂tutorial.

Let's take two water pipes as an example:

The upstream and downstream we mentioned before are respectively Observableand Observer, this time the difference is that the upstream has become Flowable, and the downstream has become Subscriber, but the connection between the water pipes is still passed subscribe(), let’s take a look at the most basic usage:

Flowable<Integer> upstream = Flowable.create(new FlowableOnSubscribe<Integer>() {
     @Override
     public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
         Log.d(TAG, "emit 1");
         emitter.onNext(1);
         Log.d(TAG, "emit 2");
         emitter.onNext(2);
         Log.d(TAG, "emit 3");
         emitter.onNext(3);
         Log.d(TAG, "emit complete");
         emitter.onComplete();
     }
}, BackpressureStrategy.ERROR); //增加了一个参数

Subscriber<Integer> downstream = new Subscriber<Integer>() {
     @Override
     public void onSubscribe(Subscription s) {
         Log.d(TAG, "onSubscribe");
         s.request(Long.MAX_VALUE);  //注意这句代码
     }
     @Override
     public void onNext(Integer integer) {
         Log.d(TAG, "onNext: " + integer);

     }

     @Override
     public void onError(Throwable t) {
         Log.w(TAG, "onError: ", t);
     }

     @Override
     public void onComplete() {
         Log.d(TAG, "onComplete");
     }
};

upstream.subscribe(downstream);

FlowableIn this code, an upstream and a downstream are created respectively Subscriber. The upstream and downstream work in the same thread, which Observableis only a little different from the previous usage. Let’s take a look at the running results first:

D/TAG: onSubscribe   
D/TAG: emit 1        
D/TAG: onNext: 1     
D/TAG: emit 2        
D/TAG: onNext: 2     
D/TAG: emit 3        
D/TAG: onNext: 3     
D/TAG: emit complete 
D/TAG: onComplete 

The result is also the same as we expected.

We noticed that this time is Observablea bit different. First of all, Flowablea parameter was added when creating it. This parameter is used to select the back pressure, that is, how to deal with the unbalanced upstream and downstream flow rates. Here we directly use BackpressureStrategy.ERRORthis This method will directly throw an exception when the upstream and downstream flow rates are unbalanced. This exception is famous MissingBackpressureException. The rest of the strategies will be explained later.

Another difference is that it onSubscribeis no longer passed to us in the downstream method Disposable, but what is the difference between them? First of all, they are both a switch between the upstream and downstream. We said before that calling Subscriptionthe method can cut off the water pipe, and the same The call of can also cut off the water pipe. The difference is that a method is added . What is the use of this method?Disposable 和 SubscriptionDisposable.dispose()Subscription.cancel()Subscriptionvoid request(long n)

If on onSubscribe方法中,不调用 s.request(Long.MAX_VALUE);就会爆异常:MissingBackpressureException. And the downstream observer Subscriber doesn't receive any of the rest of the events either.

 But this is a 同步subscription. The upstream and downstream are working 同一个线程. Every time the upstream sends an event, it should wait for the downstream to finish processing before continuing to send events. It is impossible to have the problem of unbalanced upstream and downstream flow rates.
With this question, let’s come again Take a look at the asynchronous situation:

Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                Log.d(TAG, "emit 1");
                emitter.onNext(1);
                Log.d(TAG, "emit 2");
                emitter.onNext(2);
                Log.d(TAG, "emit 3");
                emitter.onNext(3);
                Log.d(TAG, "emit complete");
                emitter.onComplete();
            }
        }, BackpressureStrategy.ERROR).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Integer>() {

                    @Override
                    public void onSubscribe(Subscription s) {
                        Log.d(TAG, "onSubscribe");
                        mSubscription = s;
                    }

                    @Override
                    public void onNext(Integer integer) {
                        Log.d(TAG, "onNext: " + integer);
                    }

                    @Override
                    public void onError(Throwable t) {
                        Log.w(TAG, "onError: ", t);
                    }

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete");
                    }
                });

This time we also removed the request code, but let the upstream and downstream work in different threads, let's see the running results:

zlc.season.rxjava2demo D/TAG: onSubscribe
zlc.season.rxjava2demo D/TAG: emit 1
zlc.season.rxjava2demo D/TAG: emit 2
zlc.season.rxjava2demo D/TAG: emit 3
zlc.season.rxjava2demo D/TAG: emit complete

Hey, this time the upstream sent all the events correctly, but the downstream didn't receive any events. What's the reason?

This is because Flowablea new way of thinking is adopted in the design 响应式拉取to better solve the problem of unbalanced upstream and downstream flow velocities控制数量 , which is 控制速度not the same as what we talked about before .

We regard request as a kind of ability, as a 下游处理事件capability, tell the upstream how many I want if the downstream can handle it, so that as long as the upstream decides how many events to send according to the processing ability of the downstream, it will not cause a swarm of bees to send out a bunch of events Come, which leads to OOM. This perfectly solves the defects of the two methods we have learned before. Filtering events will lead to event loss, and deceleration may lead to performance loss. This method not only solves the problem of event loss, Solved the problem of speed again, perfect!

But something that is too perfect means that there will be many traps. You may just be confused by its appearance and lose your mind. If you abuse or do not abide by the rules, you will also suffer.

For example, what needs to be noted here is that this effect can only be achieved when 上游正确的实现了how 根据下游的处理能力to send events. If the upstream does not care about the processing capabilities of the downstream and sends events blindly, the problem of unbalanced upstream and downstream flow rates will still occur.

Well 如何正确的去实现上游, let’s make a joke here first, and then we’ll explain it later.

After learning the request, we can explain the above two pieces of code.

First of all, the first synchronous code, why did the downstream throw MissingBackpressureExceptionan exception after the upstream sent the first event? This is because the downstream did not call the request, and the upstream thought that the downstream did not have the ability to process events, and this is a synchronous subscription. Since the downstream can’t handle it, it’s impossible for the upstream to wait forever. If this is the case, if the two water pipes work in the main thread, the interface will be stuck, so we can only throw an exception to remind us. How to solve it? In this case, it is very simple, just call request(Long.MAX_VALUE) directly downstream, or request according to the number of events sent upstream, for example, request(3) here is fine.

Then let's take a look at the second piece of code. Why does the upstream send all the events correctly when the upstream and downstream are not working in the same thread? This is because there is a water tank Flowableby default 大小为128. When the upstream and downstream work in different When in the thread, the upstream will send the event to the water tank first. Therefore, although the downstream does not call the request, the upstream saves these events in the water tank, and only when the downstream calls the request, it will be taken out of the water tank The event is sent downstream.

Well, that's all for today's tutorial. In the next section, we will learn more about FLowable, so stay tuned.

Guess you like

Origin blog.csdn.net/m0_49508485/article/details/126994890