无限计数块

时间:2019-04-12 18:37:16

标签: java project-reactor

我跑了这个

Mono<Void> mono = Mono.empty();

System.out.println("mono.block: " + mono.block());

它会产生:

mono.block: null    

符合预期。换句话说,如果block已经完成,则调用Mono将立即返回。

另一个例子,类似于真实场景。我有一个源通量,例如:

Flux<Integer> ints = Flux.range(0, 2);

我创建了一个可连接的流量,用于允许多个订阅者:

ConnectableFlux<Integer> publish = ints.publish();

在此示例中,假设有一个实际工作的订户:

publish
   .doOnComplete(() -> System.out.println("publish completed"))
   .subscribe();

和另一个只生成元素计数的订户:

Mono<Long> countMono = publish
   .doOnComplete(() -> System.out.println("countMono completed"))
   .count();

countMono.subscribe();

我连接可连接的助焊剂并打印元素计数:

publish.connect();

System.out.println("block");

long count = countMono.block();

System.out.println("count: " + count);

此打印:

publish completed
countMono completed
block

换句话说,两个订户都成功订阅并完成订阅,但随后countMono.block()被无限期阻止。

为什么会这样,我该如何做呢?我的最终目标是获取元素的数量。

1 个答案:

答案 0 :(得分:1)

您可以使用autoConnectrefCount来代替手动调用connect()

例如:

        Flux<Integer> ints = Flux.range(0, 2);
        Flux<Integer> publish = ints.publish()
                .autoConnect(2);  // new 
        publish
                .doOnComplete(() -> System.out.println("publish completed"))
                .subscribe();
        Mono<Long> countMono = publish
                .doOnComplete(() -> System.out.println("countMono completed"))
                .count();
        // countMono.subscribe();
        long count = countMono.block();
        System.out.println("count: " + count);

为什么您的示例不起作用?

这是我认为您的示例中正在发生的事情...但这是基于我的有限知识,我不确定100%正确。

  1. .publish()将上游源转化为热流
  2. 您随后订阅了两次(但由于可连接的流量尚未连接到上游,因此尚未启动)
  3. .connect()订阅上游并开始流程
  4. 上游和connect()之前完成注册的两个订阅(因为这都是在主线程中发生的)
  5. 此时,ConnectableFlux不再连接到上游,因为上游已经完成(反应堆文档详细介绍了在上游源完成后到达新订阅时ConnectableFlux发生了什么情况,所以我'不是100%可以肯定的。)
  6. block()创建一个 new 订阅。
  7. 但是由于ConnectableFlux不再连接,所以没有数据在流动
  8. 如果您要再次调用connect()(由于主线程被阻塞,则从另一个线程调用),数据将再次流动,并且block()将完成。但是,这将是一个 new 序列(而不是在步骤4中完成的原始序列)

我的示例为什么起作用?

仅创建两个订阅(而不是示例中的3个),一个来自.subscribe()调用,一个来自.block()。 2个订阅后,ConnectableFlux自动连接,因此block()订阅完成。这两个订阅共享相同的上游序列。