我对以下代码的输出有一些疑问:
101
输出:
Flux.just("a", "b", "c", "d")
.log(null, Level.INFO, true) // line: 18
.flatMap(value ->
Mono.just(value.toUpperCase()).publishOn(Schedulers.elastic()), 2)
.log(null, Level.INFO, true) // line: 21
.take(3)
.log(null, Level.INFO, true) // line: 23
.subscribe(x ->
System.out.println("Thread: " + Thread.currentThread().getName() +
" , " + x));
Thread.sleep(1000 * 1000);
问题:每个问题都与输出中的特定行有关(而不是代码中的一行)。我还将其答案添加到其中一些但我不确定我是否正确。
订阅时,订阅操作会询问1. 11:29:11 [main] INFO - | onSubscribe([Synchronous Fuseable] FluxArray.ArraySubscription) Flux.log(App.java:18)
2. 11:29:11 [main] INFO - onSubscribe(FluxFlatMap.FlatMapMain) Flux.log(App.java:21)
3. 11:29:11 [main] INFO - onSubscribe(FluxTake.TakeSubscriber) Flux.log(App.java:23)
4. 11:29:11 [main] INFO - request(unbounded) Flux.log(App.java:23)
5. 11:29:11 [main] INFO - request(unbounded) Flux.log(App.java:21)
6. 11:29:11 [main] INFO - | request(2) Flux.log(App.java:18)
7. 11:29:11 [main] INFO - | onNext(a) Flux.log(App.java:18)
8. 11:29:11 [main] INFO - | onNext(b) Flux.log(App.java:18)
9. 11:29:11 [elastic-2] INFO - onNext(A) Flux.log(App.java:21)
10. 11:29:11 [elastic-2] INFO - onNext(A) Flux.log(App.java:23)
11. Thread: elastic-2 , A
12. 11:29:11 [elastic-2] INFO - | request(1) Flux.log(App.java:18)
13. 11:29:11 [main] INFO - | onNext(c) Flux.log(App.java:18)
14. 11:29:11 [elastic-3] INFO - onNext(B) Flux.log(App.java:21)
15. 11:29:11 [elastic-3] INFO - onNext(B) Flux.log(App.java:23)
16. Thread: elastic-3 , B
17. 11:29:11 [elastic-3] INFO - | request(1) Flux.log(App.java:18)
18. 11:29:11 [elastic-3] INFO - | onNext(d) Flux.log(App.java:18)
19. 11:29:11 [elastic-3] INFO - | onComplete() Flux.log(App.java:18)
20. 11:29:11 [elastic-3] INFO - onNext(C) Flux.log(App.java:21)
21. 11:29:11 [elastic-3] INFO - onNext(C) Flux.log(App.java:23)
22. Thread: elastic-3 , C
23. 11:29:11 [elastic-3] INFO - cancel() Flux.log(App.java:21)
24. 11:29:11 [elastic-3] INFO - onComplete() Flux.log(App.java:23)
25. 11:29:11 [elastic-3] INFO - | cancel() Flux.log(App.java:18)
个元素。那么为什么事件:unbounded
正在进入管道而不是上升?我的回答:request(unbounded)
金额的请求最多为unbounded
,然后take
再次向下发送。
take
发送flatMap
信号。为什么不cancel
发送它?
最后一个问题:输出中有多个终端信号。这不是反应流规范的推论吗?
答案 0 :(得分:1)
在这种情况下,只会产生一个终端信号。
Flux.just("a", "b", "c", "d")
.log(null, Level.INFO, true) // line: 18
.flatMap(value ->
Mono.just(value.toUpperCase()).publishOn(Schedulers.elastic()), 2)
.log(null, Level.INFO, true) // line: 21
.take(3)
.log(null, Level.INFO, true) // line: 23
.subscribe(x ->
System.out.println("Thread: " + Thread.currentThread().getName() +
" , " + x), t -> {}, () -> System.out.println("Completed ""Only Once"));
这里棘手的部分是每个Reactor 3运营商都有自己的生命,并且它们都按照相同的规则运行 - 发出onComplete
以通知下游运营商不再有数据。
由于您拥有.log()
运算符和三个不同点,因此您将观察到来自onComplete
,.just
和.flatMap
的三个独立.take(3)
信号。
首先,您会看到onComplete
中的.just
,因为.flatMap
的默认行为是正常的,让我们首先尝试请求concurrency
元素,然后让我们看看它是怎么回事,因为.just
可能产生(在你的情况下)只有4个元素,在2(这是你的例子中的并发级别)请求它将发出2 onNext
以及两request(1)
后,您会看到onComplete
。反过来,发出onComplete
让.flatMap
知道当4个扁平流发出.onComplete
信号时,它将被允许向下游发出自己的onComplete
。
反过来,下游是.take(3)
运算符,也是在前三个元素发出自己的onComplete
信号之后,而不等待上游onComplete
。由于在.log
之后有.take
运算符,因此也会记录此信号。
最后,在您的流程中,您有3个独立的日志运算符,它们将记录来自3个独立运算符的3个独立onComplete
,但尽管如此,最终终端.subscribe
将只收到一个onComplete
从第一个操作员到流程。
.take
行为的小更新 .take
的核心思想是在满足剩余计数之前采用元素。由于上游可能产生超过要求的数量,我们需要有一种机制来防止发送更多数据。 Reactive-Streams规范为我们提供的机制之一是Subscription
上的协作。订阅有两个主要方法 - request
- 显示需求和cancel
- 表明即使请求的需求不满足,也不再需要数据。
如果是.take
运算符,initial demand为Long.MAX_VALUE
,则视为无限制需求。因此,停止使用可能不确定的数据流的唯一方法是cancel订阅,或者换句话说取消订阅
希望它可以帮助你:)