RxJava3.x入门(七)——背压策略

RxJava3.x入门(七)——背压策略

一、背压简介

上下游在不同的线程中,通过Observable发射,处理,响应数据流时,如果上游发射数据的速度快于下游接收处理数据的速度,这样对于那些没来得及处理的数据就会造成积压,这些数据既不会丢失,也不会被垃圾回收机制回收,而是存放在一个异步缓存池中,如果缓存池中的数据一直得不到处理,越积越多,最后就会造成内存溢出,这便是响应式编程中的背压(backpressure)问题。

背压是指在异步场景中,被观察者发送事件速度远快于观察者的处理速度的情况下,一种告诉上游的被观察者降低发送速度的策略。

在Rxjava1.0中,有的Observable支持背压,有的不支持,为了解决这种问题,2.0把支持背压和不支持背压的Observable区分开来:

  • 支持背压的有Flowable
  • 不支持背压的有Observable,Single, Maybe and Completable类。

注意事项:

  • 在订阅的时候如果使用FlowableSubscriber,那么需要通过s.request(Long.MAX_VALUE)去主动请求上游的数据项。如果遇到背压报错的时候,FlowableSubscriber默认已经将错误try-catch,并通过onError()进行回调,程序并不会崩溃。
  • 在订阅的时候如果使用Consumer,那么不需要主动去请求上游数据,默认已经调用了s.request(Long.MAX_VALUE)。如果遇到背压报错、且对Throwable的Consumer没有new出来,则程序直接崩溃。
  • 背压策略的上游的默认缓存池是128。

二、订阅关系

1.同步订阅

同步订阅就是观察者&被观察者在同一个线程工作。
他们的规则就是被观察者每发一个事情,必须等到观察者接收&处理后,才能继续发送下一个事件。
在这里插入图片描述

2.异步订阅

异步订阅就是观察者&被观察者不在同一线程工作。
他们的规则就是被观察者不需要等待观察者接收&处理后才能继续发送下一个事件,而是不断发送(到缓冲区),直到事件完毕(,此后观察者会从缓冲区取出事件)。
在这里插入图片描述

此时就有问题暴露出来:

被观察者 发送事件速度太快,而观察者 来不及接收所有事件,从而导致观察者无法及时响应 / 处理所有发送过来事件的问题,最终导致缓存区溢出、事件丢失 & OOM

那么如何解决这一问题?答案就是背压策略。

三、背压原理

  • 作用:在 异步订阅关系 中,控制事件发送 & 接收的速度
  • 解决方案 & 原理
    在这里插入图片描述
    在这里插入图片描述
    而Flowable是RxJava 2.0中被观察者的一种新实现,同时也是背压策略实现的承载者。

所以我们先简单介绍下Flowable的特点和使用。

  • Flowable 的 特点在这里插入图片描述
  • 简单使用
Flowable.create(new FlowableOnSubscribe<Integer>() {
   
            @Override
            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
   
                Log.d(TAG, "发送事件 1");
                emitter.onNext(1);
                Log.d(TAG, "发送事件 2");
                emitter.onNext(2);
                Log.d(TAG, "发送事件 3");
                emitter.onNext(3);
                Log.d(TAG, "发送事件 4");
                emitter.onNext(4);
                Log.d(TAG, "发送完成");
                emitter.onComplete();
            }
        },//背压模式使用处
         BackpressureStrategy.ERROR)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Integer>() {
   
                    @Override
                    public void onSubscribe(Subscription s) {
   
                        Log.d(TAG, "onSubscribe");
						//作用:决定观察者能够接收多少个事件
                        // 如设置了s.request(3),这就说明观察者能够接收3个事件(多出的事件存放在缓存区)
                        // 官方默认推荐使用Long.MAX_VALUE,即s.request(Long.MAX_VALUE);
                        s.request(3);
                    }

                    @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");
                    }
                });

运行结果如下:
在这里插入图片描述

可以看出Flowble & Subsciber和之前所讲述的被观察者 & 观察者相似,创建被观察者时多了一个背压策略参数,在观察者中通过request方法设置能接收几个事件。

在这里插入图片描述

四、背压策略

1.控制观察者接受事件的速度

  • 简介
    在这里插入图片描述
1.1 异步订阅情况
  • 情况1. 观察者不接收事件的情况下,被观察者继续发送事件 & 存放到缓存区,此后按需取出
        Button button = findViewById(R.id.btn);
        button.setOnClickListener(new View.OnClickListener() {
   
            @Override
            public void onClick(View v) {
   
                subscription.request(2);
            }
        });

        Flowable.create(new FlowableOnSubscribe<Integer>() {
   
                            @Override
                            public void subscribe(FlowableEmitter<Integer> emitter) throws Exception {
   
                                Log.d(TAG, "发送事件 1");
                                emitter.onNext(1);
                                Log.d(TAG, "发送事件 2");
                                emitter.onNext(2);
                                Log.d(TAG, "发送事件 3");
                                emitter.onNext(3);
                                Log.d(TAG, "发送事件 4");
                                emitter.onNext(4);
                                Log.d(TAG, "发送完成");
                                emitter.onComplete();
                            }
                        },//背压模式使用处
                BackpressureStrategy.ERROR)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Integer>() {
   
                    @Override
                    public void onSubscribe(Subscription s) {
   
                        Log.d(TAG, "onSubscribe");
                        //作用:决定观察者能够接收多少个事件
                        // 如设置了s.request(3),这就说明观察者能够接收3个事件(多出的事件存放在缓存区)
                        // 官方默认推荐使用Long.MAX_VALUE,即s.request(Long.MAX_VALUE);
                        subscription = s;
                    }

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

                    @Override
                    public void onError(Throwable t) {
   
                        Log.w(TAG, 
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值