根据JavaDoc,不按时运行的buffer
运算符版本支持背压:
http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Flowable.html#buffer-int-
但是,任何涉及基于时间的缓冲区的buffer
版本都不支持背压,例如
我理解这是因为一旦时间到了,你就无法阻止它,例如interval
运算符,由于同样的原因不支持背压。
我想要的是一个基于大小和时间的缓冲操作符,并通过将背压信号传播到上游和时间滴答生成器来完全支持背压,如下所示:
someFlowable()
.buffer(
Flowable.interval(1, SECONDS).onBackpressureDrop(),
10
);
所以现在我可以放弃背压信号。
这是rxJava2目前可以实现的吗? Project-Reactor怎么样?
答案 0 :(得分:1)
将DisposableSubscriber
用作订户时,我遇到了https://stackoverflow.com/a/55136139/6719538解决方案的问题,据我所知,该转换器不考虑来自下游订户的呼叫Suscription#request
(它可能会溢出他们)。我创建了在生产环境中经过测试的版本-BufferTransformerHonorableToBackpressure.java。 fang-yang-非常尊重想法。
答案 1 :(得分:0)
已经有一段时间了,但是我又看了一遍,以某种方式使我震惊:
public static <T> FlowableTransformer<T, List<T>> buffer(
int n, long period, TimeUnit unit)
{
return o ->
o.groupBy(__ -> 1)
.concatMapMaybe(
gf ->
gf.take(n)
.take(period, SECONDS)
.toList()
.filter(l -> !l.isEmpty())
);
}
几乎按照我的描述做。 如果我是正确的话,那是完全背压的,它将缓冲n个项目,或者如果没有收集足够的项目,将在指定的时间之后缓冲
答案 2 :(得分:0)
我又做了一个尝试,导致了一个看起来过于有效的解决方案(TM)
要求:
为什么会有人想要它?:
当我想在无限/长时间运行的流上实现缓冲时,就需要这种运算符。我想缓冲以提高效率,但是标准Flowable.buffer(n)在这里不合适,因为“无限”流可以发射k 解决方案概述: 该解决方案基于https://github.com/akarnokd/RxJava2Extensions项目中实现的 代码:
https://gist.github.com/artur-jablonski/5eb2bb470868d9eeeb3c9ee247110d4a generateAsync
和partialCollect
运算符。剩下的就是starndard RxJava2。
C
merge
与源正在使用generateAsync
的流一起传输。该流使用switchMap
发出C
的实例,这些实例实际上是超时信号。 partialCollect
,该流持有对“ API”对象的引用,以向generateAsync
上游发送项目。这是一种反馈循环,它从paritialCollect
通过“ API”对象到generateAsync
,然后反馈到partialCollect
。这样,partialCollect
可以在接收到缓冲区中的第一个元素后发出将有效启动超时的信号。如果在超时之前缓冲区未满,它将导致一个空C
(不包含任何值)的实例流回partialCollect
。它将检测到它为超时信号,并向下游释放聚合缓冲区。如果由于达到最大大小而释放了缓冲区,它将被释放,并且下一个项目将开始另一个超时。任何超时信号(空C
的实例)迟到,也就是由于达到最大大小而在释放缓冲区之后,将被忽略。可能的原因是,实例化并发送超时信号项的partialCollect
可能会流回去。检查该物品的身份可以检测到延迟超时还是合法超时信号。
答案 3 :(得分:0)
我最近遇到了问题,这是我的实现。可以这样使用:
Flowable<List<T>> bufferedFlow = (some flowable of T)
.compose(new BufferTransformer(1, TimeUnit.MILLISECONDS, 8))
它通过您指定的计数支持背压。
以下是实现:https://gist.github.com/driventokill/c49f86fb0cc182994ef423a70e793a2d