Java 使用replay(selectorFoo)但不使用publish(selectorFoo)时的OOM
这与OOM冲突:Java 使用replay(selectorFoo)但不使用publish(selectorFoo)时的OOM,java,rx-java2,project-reactor,Java,Rx Java2,Project Reactor,这与OOM冲突: Flowable.range(1, 5000) .map(__ -> new byte[1024 * 1024]) .replay( fb -> fb.take(1) .concatMap(__ -> fb) ,1 ) .count() .toFlowable() .bloc
Flowable.range(1, 5000)
.map(__ -> new byte[1024 * 1024])
.replay(
fb ->
fb.take(1)
.concatMap(__ -> fb)
,1
)
.count()
.toFlowable()
.blockingSubscribe(c -> System.out.println("args = [" + c + "]"));
我认为这是因为replay
保留了上游的排放量,即使我认为1
缓冲区大小提示不会。。。。我错过了什么
这不会崩溃:
Flowable.range(1, 5000)
.map(__ -> new byte[1024 * 1024])
.publish(
fb ->
fb.take(1)
.concatMap(first -> fb.startWith(first))
,1
)
.count()
.toFlowable()
.blockingSubscribe(c -> System.out.println("args = [" + c + "]"));
但我不确定我是否能保证从上游获得所有的排放量…我已经对此进行了调查,并找到了问题的原因:RxJava 2中的
回放中有一个bug
发生的情况是,replay
在局部变量中保存对2个订阅者的引用,一个用于take
,另一个用于concatMap
的内部使用者,因此从主线程到失效的take
仍然引用第一个项目。由于有界重播使用了一个链表,因此第一个项目通过其“下一个”链接不断引用更新的项目,并最终耗尽内存
publish
不保留对旧值的引用,因此这不是问题。感谢您查看此内容。在第二个示例中,使用publish()
在take(1)
获取其项目和concatMap
订阅之间,是否可能丢失上游排放?我试图以各种方式打破它,但我似乎总是得到所有的排放,但rxJava2背后的策划人的确认会更令人信服:)。另外,我是否需要在github上为此提交问题?噢,天哪,我刚刚看到它已经被修复并合并到下一个版本:)。谢谢我将尝试回答关于publish()
示例的问题。反应式规范说明不能同时调用onNext()
。因此,只有在上一个onNext()
完成时才能调用onNext()
。由于publish()
的内部流没有引入任何异步性,这意味着在take(1)
上调用第一个onNext()
,然后在concatMap()
上调用onNext()
,后者将调用其内部函数并订阅生成的Flowable
。然后才允许调用下一个onNext()
,因此在给定示例中不会丢失任何排放。