在以下示例中,我无法弄清楚为什么添加executeWithFork
会阻止任务运行:
import java.util.concurrent.TimeUnit
import monix.execution.schedulers.SchedulerService
import monix.reactive.subjects.ConcurrentSubject
object Sandbox {
def main(args: Array[String]): Unit = {
implicit val scheduler: SchedulerService =
monix.execution.Scheduler(java.util.concurrent.Executors.newCachedThreadPool())
val input = ConcurrentSubject.publish[String]
// prints nothing
input.foreachL(println).executeWithFork.runAsync
// this works:
// input.foreachL(println).runAsync
input.onNext("one")
input.onNext("two")
scheduler.shutdown()
scheduler.awaitTermination(1, TimeUnit.MINUTES, monix.execution.Scheduler.Implicits.global)
}
}
答案 0 :(得分:1)
您看到的行为是两个事实的结果:
使用executeWithFork
会给线程切换带来一些额外的延迟
您使用ConcurrentSubject.publish
(例如,与replay
相反)。如果您打开PublishSubject
的文档,您可能会看到
PublishSubject
仅向订户发出在订阅时间之后由源发出的那些项目。
换句话说,您在发布"one"
和"two"
的主线程与必须订阅input
来获取数据的派生线程之间存在竞争条件。结果取决于哪个线程赢得竞争:订阅丢失之前发布的所有数据。在我的硬件中,我几乎总是看到"two"
,有时甚至看到"one"
,您的结果可能会有所不同。
最简单的测试方法是在第一个Thread.sleep(100)
之前添加input.onNext
,并且您应该每次都看到两个事件。您还可以尝试推动事件而不只是2个,以确保不会丢失所有内容。