Rx java 为什么在嵌套流中使用computation()调度程序会导致死锁?

Rx java 为什么在嵌套流中使用computation()调度程序会导致死锁?,rx-java,rx-java2,Rx Java,Rx Java2,最近我写了一些复杂的基于RX的流程,发现它在特定情况下总是会产生死锁。我花了几个小时来找出问题所在,似乎可以在这个简单的例子中重现: public static void main(String[] args) throws InterruptedException { Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9) .flatMap(x -> Observable.fromIterable(produceMultiple(x)

最近我写了一些复杂的基于RX的流程,发现它在特定情况下总是会产生死锁。我花了几个小时来找出问题所在,似乎可以在这个简单的例子中重现:

public static void main(String[] args) throws InterruptedException {
    Observable.just(1, 2, 3, 4, 5, 6, 7, 8, 9)
        .flatMap(x -> Observable.fromIterable(produceMultiple(x)))
        .subscribeOn(Schedulers.computation())
        .subscribe(System.out::println);

    Thread.sleep(50_000);
}

private static List<Integer> produceMultiple(int x) {
    return Observable.range(1, x)
        .flatMap(y -> Observable.fromCallable(() -> {
                Thread.sleep(1000);
                return 10 * x + y;
            }).subscribeOn(Schedulers.computation())
        ).toList().blockingGet();
}
publicstaticvoidmain(String[]args)抛出InterruptedException{
可观察的。只是(1,2,3,4,5,6,7,8,9)
.flatMap(x->Observable.fromIterable(produceMultiple(x)))
.subscribeOn(Schedulers.computation())
.subscribe(System.out::println);
睡眠(50_000);
}
私有静态列表produceMultiple(int x){
返回可观测范围(1,x)
.flatMap(y->Observable.fromCallable(()->{
睡眠(1000);
返回10*x+y;
}).subscribeOn(Schedulers.computation())
).toList().blockingGet();
}
此程序应打印以下值:11、21、22、31、32、33、…、99。通常,值可以表示为XY。每个组X中的值顺序可以是随机的,但组的顺序应该是升序。如果previous仍在计算,则不应发出新组(这是我的原始情况)

问题是,如果您运行这段代码,您将只看到前几个元素的输出-我相信它与处理器的数量相关,因为computation()调度器使用固定的线程池大小

你知道为什么会这样吗?这似乎有些奇怪,因为主链的数字(1、2、3、…)是在池中的单个线程上处理的,并且每次produceMultiple使用blockingGet()完成其作业时,其他线程都应该是空闲的


如果您修改任何提供不同调度器的subscribeOn()(或者一个是computation(),另一个是computation()),一切正常。此外,如果我从自定义线程池执行器(绑定到4个线程)创建调度程序,它仍然可以工作

不要在
计算
调度程序上使用
blockingGet
,因为您可能会阻止代码其他部分使用的后台线程。您甚至不必在代码中使用它,只需从
produceMultiple
返回
Observable

static void main(字符串[]args)抛出InterruptedException{
可观察的。只是(1,2,3,4,5,6,7,8,9)
.flatMap(x->produceMultiple(x))
.subscribeOn(Schedulers.computation())
.subscribe(System.out::println);
睡眠(50_000);
}
静态可观测生产倍数(int x){
返回可观测范围(1,x)
.flatMap(y->Observable.fromCallable(()->{
睡眠(1000);
返回10*x+y;
}).subscribeOn(Schedulers.computation())
);
}

您的解决方案还可以,但它稍微改变了我对组处理的假设。但是,如果您将main方法中的
flatMap
更改为
concatMap
,则一切都按预期进行。尽管如此,我仍然不知道为什么我上面发布的示例代码没有结束。。。并不是说“它可能阻塞”,它总是在同一时刻阻塞。看起来计算调度器中充满了来自
produceMultiple
的任务,这些任务永远不会释放调度器,即使它们调用
onComplete