什么是背压模式,在rxjava1系列是没有背压模式的,但是在rxjava2中加入了背压。那是因为在rxjava1中,如果上游不停地发射,下游处理不过来(阻塞),就会出现内存泄漏。为了解决这个问题,就引入了背压。背压的上游被观察者是Flowable,下游观察者是Subscriber。使用方式和Observable极为相似。了解到背压,就不得不说背压的几种策略模式:
- ERROR:上游不停的发射大量事件,下游阻塞了 处理不过来,放入缓存池,如果池子满了,就会抛出异常,最大128个事件
- BUFFER:上游不停的发射大量事件,下游阻塞了 处理不过来,放入缓存池,”等待“下游来接收事件处理
- DROP:上游不停的发射大量事件,下游阻塞了 处理不过来,放入缓存池,如果池子满了,就会把后面发射的事件丢弃
- LASTEST:在LATEST策略下如果此时Flowable的缓存池的数据超过了最大值128,此时如果Flowable继续发送数据的话, 缓存池会将之后的数据都给丢弃掉,但是还会缓存发送的事件中最后一次发送的数据。
下面,针对上游同步和异步两种情况,对不同得背压模式进行测试。
一、同步
1、ERROR
测试代码如下:
(1)不执行Subscription.request()方法
测试结果如下:
发生了异常,并且在下游onError()方法中打印了异常信息。
(2)执行Subscription.request()方法
测试结果仍然和上面一致,但是当我们把发送的事件个数设置为128以内(上线发送了200个事件),测试结果如下:
这里下游处理了20个事件,即调用了s.request(20);
2、BUFFER
测试代码如下:
策略模式改为BUFFER。
测试结果如下:
(1)不执行Subscription.request()方法
不会发生异常。
(2)执行Subscription.request()方法
即使上游发送的事件数超过128,都不会发生异常。
3、DROP
测试代码如下:
策略模式改为DROP。
测试结果如下:
(1)不执行Subscription.request()方法
不会发生异常。
(2)执行Subscription.request()方法
发现上游发射了200个事件,但是下游最大接受了128个事件,其他的事件被丢弃了。
4、LASTEST
测试代码如下:
策略模式改为LASTEST。
测试结果如下:
(1)不执行Subscription.request()方法
不会发生异常。
(2)执行Subscription.request()方法
发现上游发射200个事件,下游只打印了前128个事件和最后一个事件。
背压模式,上游同步发射总结:
- ERROR:上游发射事件不能超过128个,并且上游发射的事件如果下游没有及时处理(调用request()方法),都会抛出异常。
- BUFFER:该模式下不会出现异常,并且发射的事件数量不受限制
- DROP:上游发射事件超过128个,将会丢弃掉剩余的事件
- LASTEST:上游发射事件超过128个,将会丢弃掉缓存池所有的事件,但是仍然会缓存发送最后的一次事件。
二、异步
1、ERROR
测试代码如下:
测试结果如下:
(1)不执行Subscription.request()方法
不会发生异常。
(2)执行Subscription.request()方法
如果发射的事件数超过128,会抛出异常,如下:
反之,如下:
2、BUFFER
和同步测试一致
3、DROP
和同步测试一致
3、LASTEST
和同步测试一致
背压模式,上游异步发射总结:
- ERROR:异步模式下,只要发射的事件数不超过128个,那么无论下游有没有处理事件(调用request()方法),都不会抛出异常。