在发布者完成前解雇时的单声道

时间:2019-07-12 22:15:09

标签: java project-reactor

示例代码:

Flux<Integer> fluxSrc = Flux.<Integer> create(e -> {
   e.next(1);

   try {
      Thread.sleep(500);
   } catch (InterruptedException e1) {
      throw new RuntimeException(e1);
   }

   e.complete();
})
   .publishOn(Schedulers.single())
   .publish().autoConnect(2);

Flux<Integer> fluxA = fluxSrc
   .publishOn(Schedulers.single())
   .map(j -> 10 + j);

fluxA.subscribe(System.out::println);

Mono<Integer> monoB = fluxSrc
   .publishOn(Schedulers.single())
   .reduce(20, (j, k) -> {
      try {
         Thread.sleep(1000);
      } catch (InterruptedException e1) {
         throw new RuntimeException(e1);
      }
      return j + k;
   });

monoB.subscribe(System.out::println);

Mono.when(fluxA, monoB)
   .block();

System.out.println("After");

这将产生以下输出:

11
After
21

为什么它不等待两个发布者(fluxAmonoB)都完成?我应该如何构造代码,以确保在到达After之前所有发布者都已完成?

1 个答案:

答案 0 :(得分:1)

通过使用.publish()fluxSrc变成热通量。考虑:

  

另一方面,热门发布者不依赖任何数量的   订阅者。他们可能会立即开始发布数据,并且会   每当有新的订户进入时,都应继续这样做(在这种情况下)   表示订户只会看到它之后发出的新元素   已订阅)。对于热门发布者来说,确实确实发生了一些事   您订阅。

https://projectreactor.io/docs/core/release/reference/#reactor.hotCold

解决此问题的一种方法是摆脱publish并在冷流下运行。另一种是将.autoConnect(2);更改为.autoConnect(3);-这是因为您要在第三个订阅时开始处理数据-达到Mono.when(fluxA, monoB).block();(先前的是fluxA.subscribe和{{1} }。

修改monoB.subscribe确实等待源代码完成,但是它从先前的订阅中获得了onComplete信号。

可能发生的事情是:

  1. 助焊剂A被When所限制,发出11并打印出来。
  2. 助焊剂B被fluxA.subscribe(System.out::println);所取代,并开始减少。
  3. monoB.subscribe(System.out::println);被添加了(这触发了“多播”-流量被第二次添加了。)
  4. 还原开始,结果为21。
  5. 另一个缩减开始,并立即以结果20完成(减少空流-另一个缩减仅消耗了fluxSrc中的项目)。
  6. 通量A发送给两个子订户onComplete。
  7. 通量B发送给Complete,结果减少=20。它被传递到Mono.when进行的订阅,这就是为什么它不被打印的原因。
  8. 自从Mono。删除以来,这两个通量都在Complete上发送,因此打印了Mono.when
  9. 在该时间附近,第一次还原以值21完成,该值已传递给After