Multithreading RxJava并行化是否打破了可观察契约?

Multithreading RxJava并行化是否打破了可观察契约?,multithreading,parallel-processing,reactive-programming,rx-java,Multithreading,Parallel Processing,Reactive Programming,Rx Java,Ben Christensen指出,目前在RxJava中实现并行性的最佳方法是创建另一个可观察的,并在调度器上订阅它,如下所示 streamOfItems.flatMap(item -> { doStuffWithItem(item).subscribeOn(Schedulers.io()); }); 但是,声明可以调用onNext()调用任意次数,只要调用不重叠。那么,链的其余部分中的任何操作符现在都可以很容易地打破这个规则(除非它们显式地执行某种同步/序列化) 我的印象是,Rx

Ben Christensen指出,目前在RxJava中实现并行性的最佳方法是创建另一个
可观察的
,并在调度器上订阅它,如下所示

streamOfItems.flatMap(item -> {
   doStuffWithItem(item).subscribeOn(Schedulers.io());
});
但是,声明可以调用
onNext()
调用任意次数,只要调用不重叠。那么,链的其余部分中的任何操作符现在都可以很容易地打破这个规则(除非它们显式地执行某种同步/序列化)

我的印象是,RxJava更喜欢一次在一个线程上保持一个发射流,并在特定的操作符上从一个线程切换到另一个线程,但从不并行(如下所示)

用一种平行的方法,我知道图表可能看起来像这样,而在我看来,那看起来很重叠

par subscribeOn() thread 3    -------------------------Y-----Y---------------
par subscribeOn() thread 2    ---------------------------Y---Y---------------
par subscribeOn() thread 1    -------------------------Y-------------Y-------
initial subscribeOn() thread  ----X----X----X----X---------------------------

我是否误解了什么或做出了广泛的假设?并行性是否打破了
可观察的
契约?这是否在某种程度上使它变得不可取?

如果您使用的是标准运算符,那么没有什么会破坏可观察契约,因为无论何时发生并发,运算符都会序列化其输出。在您的示例中,
flatMap
这样做是为了确保其输出是连续的(尽管接收线程可能会来回切换)


但是,如果同一管道的不同阶段由异步边界或可能执行线程仲裁的运算符分隔,则这通常不适用于同一管道的不同阶段。

好的,现在更有意义了。。。因此,大多数操作符都进行序列化,即使是像map()这样的简单操作符,还是只有像flatMap()这样需要序列化的操作符?不处理多个源或调度程序的操作符本身不进行序列化,而是让事件按原样通过。因此,如果有一个恶意源同时调用onNext,map会很高兴地传递它。要修复这些源代码,您需要在其上应用
.serialize()
。恶意源代码是否会由于线程安全问题而使任何内置操作符处于危险之中?与toList()类似?
toList
使用ArrayList.add,因此具有与手动和并发操作相同的效果。如果没有合同,几乎所有的运营商都可能违约。这正是我的理由。。。非常感谢。我可以理解为什么parallel()操作符被弃用和删除,因为它很容易被误解和误用。
par subscribeOn() thread 3    -------------------------Y-----Y---------------
par subscribeOn() thread 2    ---------------------------Y---Y---------------
par subscribeOn() thread 1    -------------------------Y-------------Y-------
initial subscribeOn() thread  ----X----X----X----X---------------------------