RxJava2.0简介(五)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Viiou/article/details/90382527

本文参考:https://www.jianshu.com/p/a75ecf461e02

3.9 背压的策略

我们在上一篇文章中说到了背压的策略问题,总共有五个策略,在这里列个表格展示一下吧。

策略 含义
BackpressureStrategy.MISSING 如果流的速度无法保持同步,可能会抛出MissingBackpressureException或IllegalStateException
BackpressureStrategy.ERROR 会在下游跟不上速度时抛出MissingBackpressureException
BackpressureStrategy.BUFFER 上游不断的发出onNext请求,直到下游处理完,也就是和Observable一样了,缓存池无限大,最后直到程序崩溃
BackpressureStrategy.DROP 会在下游跟不上速度时把onNext的值丢弃
BackpressureStrategy.LATEST 会一直保留最新的onNext的值,直到被下游消费掉

我们先看BackpressureStrategy.BUFFER。

Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                for (int i = 0; ; i++) {
                    Log.i(TAG, "subscribe: " + i);
                    emitter.onNext(i);
                }
            }
        }, BackpressureStrategy.BUFFER);

        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                mSubscription = s;
                Log.i(TAG, "onSubscribe: ");
            }

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

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

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

        flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);

在这里插入图片描述
BUFFER策略使得Flowable与Observable相似,它会改变Flowable缓存区的大小,将数据不停的放到这里。在实验的时候你可能会感觉Flowable内存占用率的上升时间比较慢,这是因为Flowable在响应式拉取方面做了更多的操作,所以性能方面有所损失也是在所难免的。

从这个角度看,不能因为使用了Flowable就放松代码的要求,一味的滥用肯定会造成OOM或者别的问题。

然后是DROP。

private void test25() {
        Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                for (int i = 0; i < 1000; i++) {
                    emitter.onNext(i);
                }
            }
        }, BackpressureStrategy.DROP);
        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                Log.i(TAG, "onSubscribe: ");
                mSubscription = s;
            }

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

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

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete: ");
            }
        };
        flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);

    }

    public void requestClick(View view) {
        //点击一次按钮 请求一次数据
        mSubscription.request(128);
    }

在这里插入图片描述
下游处理速度跟不上时Drop会把值丢弃掉。Flowable的缓存区是128,所以上游会先将0~127存储到缓存区,然后到了128,Flowable会直接将128丢掉,剩下的值也类似。当我们requset(128)时,上游将缓存区中的128个数字发送到下游,下游然后打印出来。但是当我们再此点击时,却不会打印数据了,因为for循环跑完了,没有数据存储到缓存区,所以没有打印。

然后是LATEST。

private void test26() {
        Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                for (int i = 0; i < 1000; i++) {
                    emitter.onNext(i);
                }
            }
        }, BackpressureStrategy.LATEST);
        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                mSubscription = s;
                Log.i(TAG, "onSubscribe: ");
            }

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

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

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete: ");
            }
        };
        flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);
    }

    public void requestClick(View view) {
        //点击一次按钮 请求一次数据
        mSubscription.request(128);
    }

在这里插入图片描述
从Log中可以看到,与DROP不同的是,LATEST总是可以获取最后一个onNext数值。

MISSING就比较好理解了,下游无法处理上游数据时,便会抛出错误,与ERROR相似。抛出的Log如下所示:

I/RxJavaTestHaHa: onError: io.reactivex.exceptions.MissingBackpressureException: Queue is full?!

至此,背压的策略我们就过了一遍,

然后是一个小例子,如果是别人的Flowable我们怎么选择背压策略。

onBackpressureBuffer()

onBackpressureDrop()

onBackpressureLatest()

Flowable.interval(1, TimeUnit.MICROSECONDS)
                .onBackpressureDrop()  //加上背压策略
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Long>() {
                    @Override
                    public void onSubscribe(Subscription s) {
                        Log.d(TAG, "onSubscribe");
                        mSubscription = s;
                        s.request(Long.MAX_VALUE);
                    }

                    @Override
                    public void onNext(Long aLong) {
                        Log.d(TAG, "onNext: " + aLong);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

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

                    @Override
                    public void onComplete() {
                        Log.d(TAG, "onComplete");
                    }
                });
3.10 响应式请求

在前文中受到了Flowable是响应式请求,既然下游能request,那在上游肯定可以得到这个数值,这个值就是FlowableEmitter中的requested。

现在同步的DEMO中看一下是如何请求的。

Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                Log.i(TAG, "subscribe: " + emitter.requested());

                emitter.onNext(3);
                Log.i(TAG, "subscribe: " + emitter.requested());

                emitter.onNext(2);
                Log.i(TAG, "subscribe: " + emitter.requested());

                emitter.onNext(1);
                Log.i(TAG, "subscribe: " + emitter.requested());

                emitter.onComplete();
                Log.i(TAG, "subscribe: " + emitter.requested());

            }
        }, BackpressureStrategy.ERROR);

        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                mSubscription = s;
                mSubscription.request(100);
                mSubscription.request(30);
                Log.i(TAG, "onSubscribe: ");
            }

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

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

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete: ");
            }
        };
        flowable.subscribe(subscriber);
I/RxJavaTestHaHa: onSubscribe: 
I/RxJavaTestHaHa: subscribe: 130
I/RxJavaTestHaHa: onNext: 3
I/RxJavaTestHaHa: subscribe: 129
I/RxJavaTestHaHa: onNext: 2
I/RxJavaTestHaHa: subscribe: 128
I/RxJavaTestHaHa: onNext: 1
I/RxJavaTestHaHa: subscribe: 127
I/RxJavaTestHaHa: onComplete: 
I/RxJavaTestHaHa: subscribe: 127

从Log中可以直观的看到,多次request时是会做加法,加在一起,100+30=130,发送一个onNext事件时是会做减法,而onComplete事件不会减少requested的值,那在异步中是什么样的。

Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                Log.i(TAG, "subscribe: " + emitter.requested());

                emitter.onNext(3);
                Log.i(TAG, "subscribe: " + emitter.requested());

                emitter.onNext(2);
                Log.i(TAG, "subscribe: " + emitter.requested());

                emitter.onNext(1);
                Log.i(TAG, "subscribe: " + emitter.requested());

                emitter.onComplete();
                Log.i(TAG, "subscribe: " + emitter.requested());

            }
        }, BackpressureStrategy.ERROR);

        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                mSubscription = s;
                mSubscription.request(100);
                mSubscription.request(30);
                Log.i(TAG, "onSubscribe: ");
            }

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

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

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete: ");
            }
        };
        flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);
I/RxJavaTestHaHa: onSubscribe: 
I/RxJavaTestHaHa: subscribe: 128
I/RxJavaTestHaHa: subscribe: 127
I/RxJavaTestHaHa: subscribe: 126
I/RxJavaTestHaHa: subscribe: 125
I/RxJavaTestHaHa: onNext: 3
I/RxJavaTestHaHa: onNext: 2
I/RxJavaTestHaHa: onNext: 1
I/RxJavaTestHaHa: onComplete: 

从log中可以看出这个值变成了128,为什么不是130?

当上下游工作在不同的线程里时,每一个线程里都有一个requested,而我们调用request(130)时,实际上改变的是下游主线程中的requested,而上游中的requested的值是由RxJava内部调用request(n)去设置的,这个调用会在合适的时候自动触发。

简单来说就是在异步中,下游无法设置上游的requested,得靠系统自己选择一个默认值。但是在同步中,因为在同一个线程中,下游可以设置上游的requested。

private void test30(){
        Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                boolean sign;
                for (int i = 0; i<181; i++) {
                    sign = false;
                    while (emitter.requested() == 0) {
                        if (!sign) {
                            Log.i(TAG, "subscribe: I can't give you anymore");
                        }
                        sign = true;
                    }
                    Log.i(TAG, "subscribe: " + i + "  " + emitter.requested());
                    emitter.onNext(i);
                }
            }
        }, BackpressureStrategy.ERROR);

        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                mSubscription = s;
                Log.i(TAG, "onSubscribe: ");
            }

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

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

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete: ");
            }
        };
        flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);
    }

    public void requestClick(View view) {
        //点击一次按钮 请求一次数据
        mSubscription.request(90);
    }

这个的Log太长了,我就不粘了,但是如果大家仔细看到话,会发现一个奇怪的数字96。对,不是128,是96。128我们能理解,是Flowable缓存区水缸的大小,那96是什么数字?96也是默认的数字,前面不是说过在异步中,下游无法给上游设置requested,上游的requested刚开始默认是128,那下次请求时requested会是多少,是96。如果你观察Log仔细的话会发现,点击一次按钮,只调用了下游的onNext方法,因为上游存储的128个数据满足上游的使用。然后再调用一次的话,剩下的数据不够了,才会改变requested,而这个值改为了96。

下面的这个例子更能说明我的意思

Flowable<Integer> flowable = Flowable.create(new FlowableOnSubscribe<Integer>() {
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
                boolean sign;
                for (int i = 0; i<1801; i++) {
                    sign = false;
                    while (emitter.requested() == 0) {
                        if (!sign) {
                            Log.i(TAG, "subscribe: I can't give you anymore");
                        }
                        sign = true;
                    }
                    Log.i(TAG, "subscribe: " + i + "  " + emitter.requested());
                    emitter.onNext(i);
                }
            }
        }, BackpressureStrategy.ERROR);

        Subscriber<Integer> subscriber = new Subscriber<Integer>() {
            @Override
            public void onSubscribe(Subscription s) {
                mSubscription = s;
                Log.i(TAG, "onSubscribe: ");
            }

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

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

            @Override
            public void onComplete() {
                Log.i(TAG, "onComplete: ");
            }
        };
        flowable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(subscriber);
    }

    public void requestClick(View view) {
        //点击一次按钮 请求一次数据
        mSubscription.request(129);
    }

猜你喜欢

转载自blog.csdn.net/Viiou/article/details/90382527
今日推荐