Java 项目反应器:处理快速和慢速发布程序

Java 项目反应器:处理快速和慢速发布程序,java,reactive-programming,project-reactor,reactive,Java,Reactive Programming,Project Reactor,Reactive,考虑以下代码: AtomicInteger counter1 = new AtomicInteger(); AtomicInteger counter2 = new AtomicInteger(); Flux<Object> source = Flux.generate(emitter -> { emitter.next("item"); }); Executor executor1 = Executors.newFixedThreadPool(32); Execu

考虑以下代码:

AtomicInteger counter1 = new AtomicInteger();
AtomicInteger counter2 = new AtomicInteger();

Flux<Object> source = Flux.generate(emitter -> {
    emitter.next("item");
});

Executor executor1 = Executors.newFixedThreadPool(32);
Executor executor2 = Executors.newFixedThreadPool(32);

Flux<String> flux1 = Flux.merge(source).concatMap(item -> Mono.fromCallable(() -> {
        Thread.sleep(1);
        return "1_" + counter1.incrementAndGet();
}).subscribeOn(Schedulers.fromExecutor(executor1)));

Flux<String> flux2 = Flux.merge(source).concatMap(item -> Mono.fromCallable(() -> {
    Thread.sleep(100);
    return "2_" + counter2.incrementAndGet();
}).subscribeOn(Schedulers.fromExecutor(executor2)));

Flux.merge(flux1, flux2).subscribe(System.out::println);
AtomicInteger计数器1=新的AtomicInteger();
AtomicInteger计数器2=新的AtomicInteger();
通量源=通量生成(发射器->{
(b)下一项(“项目”);
});
Executor Executor 1=Executors.newFixedThreadPool(32);
Executor Executor 2=Executors.newFixedThreadPool(32);
Flux flux1=Flux.merge(source).concatMap(item->Mono.fromCallable)(()->{
睡眠(1);
返回“1_”+计数器1.incrementAndGet();
}).subscribeOn(Schedulers.fromExecutor(Executor 1));
Flux flux2=Flux.merge(source).concatMap(item->Mono.fromCallable)(()->{
睡眠(100);
返回“2_”+计数器2.incrementAndGet();
}).subscribeOn(Schedulers.fromExecutor(Executor 2));
Flux.merge(flux1,flux2).subscribe(System.out::println);
您可以看到,一个发布服务器比另一个发布服务器快100倍。尽管如此,在运行代码时,似乎所有的数据都被打印出来了,但两个发布者之间存在巨大的差距,这增加了超时时间

值得注意的是,当更改数字时,
executer2
将有
1024个
线程,
executer1
将只有
1
线程,然后我们仍然看到随着时间的推移,差距越来越大

我的期望是,在相应地调整线程池之后,发布者将获得平衡

  • 我希望在发布者之间实现平衡(相对于线程池大小和处理时间)

  • 如果我等得够久会发生什么?换句话说,是否会出现背压?(默认情况下,我猜这是一个运行时异常,对吗?)

  • 我不想删除项目,也不想出现运行时异常。相反,正如我所提到的,我希望系统在资源和处理时间方面达到平衡-上面的代码承诺了吗?


    谢谢

    本例中的
    Flux
    对象不是
    ParallelFlux
    对象,因此它们只使用一个线程。

    如果您创建一个能够处理数千个线程的调度程序,并将其传递给
    Flux
    对象中的一个,那么这并不重要,因为它们将不被使用,这正是本例中发生的情况。没有反压力,也不会导致异常-它只是使用一个线程以尽可能快的速度运行

    如果要确保
    通量
    充分利用可用的1024个线程,则需要调用
    .parallel(1024)

    然而,有一句警告:

    我希望在发布者之间实现平衡(相对于线程池大小和处理时间)


    您不能在这里选择数字来平衡输出,至少不可靠或以任何有意义的方式-线程调度将完全是任意的。如果您想这样做,那么可以使用,允许您显式地调用订阅使用者上的
    request()
    。这样,您就可以通过只请求准备处理的尽可能多的元素来提供背压。

    两个通量分别订阅给定的源。因此,最终他们实际上从两个独立的来源消费。这就是你想要的吗?我想我明白了。我有一个大的线程池并不重要,因为订阅服务器本身是单线程的,所以它使用池中的一个线程,并基本上等待它完成。顺便说一下,我知道你不能完全同步工作。我的意思是,根据预期(如果我可以说的话),工作将是平衡的。非常感谢您的详细回答!
    ParallelFlux<String> flux1 = Flux.merge(source).parallel(1).concatMap(item -> Mono.fromCallable(() -> {
        Thread.sleep(1);
        return "1_" + counter1.incrementAndGet();
    }).subscribeOn(Schedulers.fromExecutor(executor1)));
    
    ParallelFlux<String> flux2 = Flux.merge(source).parallel(1024).concatMap(item -> Mono.fromCallable(() -> {
        Thread.sleep(100);
        return "2_" + counter2.incrementAndGet();
    }).subscribeOn(Schedulers.fromExecutor(executor1)));
    
    ...
    2_17075
    2_17076
    1_863
    1_864
    2_17077
    1_865
    2_17078
    2_17079
    ...