[英]How does flatMap manage threads?
Flux.just("a", "b", "c")
.log(null, Level.INFO,true) // line 18
.flatMap(value -> Mono.just(value.toUpperCase())
.publishOn(Schedulers.elastic()), 2)
.log(null, Level.INFO,true) // line 21
.subscribe();
一些输出:
13:03:46 [main] INFO - | request(2) Flux.log(App.java:18)
13:03:46 [main] INFO - | onNext(a) Flux.log(App.java:18)
13:03:46 [main] INFO - | onNext(b) Flux.log(App.java:18)
13:03:46 [elastic-2] INFO - onNext(A) Flux.log(App.java:21)
13:03:46 [elastic-2] INFO - | request(1) Flux.log(App.java:18)
13:03:46 [main] INFO - | onNext(c) Flux.log(App.java:18)
13:03:46 [elastic-3] INFO - onNext(B) Flux.log(App.java:21)
13:03:46 [elastic-3] INFO - | request(1) Flux.log(App.java:18)
13:03:46 [elastic-2] INFO - onNext(C) Flux.log(App.java:21)
13:03:46 [elastic-2] INFO - | request(1) Flux.log(App.java:18)
13:03:46 [main] INFO - | onComplete() Flux.log(App.java:18)
13:03:46 [main] INFO - onComplete() Flux.log(App.java:21)
问题:
为什么flatMap
从main
线程请求 2 个元素,然后从其他线程请求更多元素?
为什么subscribe
不由main
线程处理?
第一个Subscription.request
金额取决于您指定的并发级别,即2
。 由于您在主线程中调用.subscribe
,因此将在该线程上准确调用第一个prefetch
请求。
让我们看看下一个架构:
.subscribe()[Thread main]
-> FluxLog.source.subscribe()[Tread Main]
-> FluxFlatMap.source.subscribe()[ThreadMain]
-> FluxJust.subscriber.onSubscribe()
-> FluxFlatMap.subscription.request(concurrency)[Thread Main]
然后,从那一点开始将是铁杆:)。 由于您的内部流将由FlatMapInner
订阅,它将观察Scheduler.elastic
上的所有信号(onNext、onError、onComplete)(因为您的.publishOn
)。 反过来,当内部流完成时,其onComplete
上的FlatMapInnner
将通知 main FlatMapMain
,它是整个flatMap
机制的驱动程序。 FlatMapInner
和FlatMapMain
之间的交互正在通过FlatMapMain.innerComplete
。 由于从 FlatMapMain 的角度来看,内部FlatMapInner
正在扮演Queue
的角色,因此所有元素都将被drained
。 保持冷静,如果您不知道这里发生了什么,请不要惊慌。 该方法的所有想法是从内部流中排出数据并将其发送到下游,然后向上游请求新的数据部分。 你应该记住的事情是, innerComplete
是从FlatMapInner.onComplete
调用的,它被移动到另一个调度程序,所以这意味着下一个Subscription.request
将从Mono.just(value.toUpperCase()).publishOn(Schedulers.elastic())
指定的线程Mono.just(value.toUpperCase()).publishOn(Schedulers.elastic())
因此,示意性地,该过程如下所示:
FluxFlatMap.FlatMapMain.onNext [Thread Main]
-> Publisher m = mapper(...)
-> m.subscribe(new FluxFlatMap.FlatMapInner())
-> FluxFlatMap.FlatMapInner.onNext("a") [Thread Elastic N]
-> LambdaSubscriber.onNext("c") [Thread Elastic N]
-> FluxFlatMap.FlatMapInner.onComplete() [Thread Elastic N]
-> FluxFlatMap.FlatMapMain.drainLoop() [Thread Elastic N]
-> FluxFlatMap.FlatMapMain.drainLoop() [Thread Elastic N] { ... subscription.request(amountOfCompletedInners)
-> FlatMap.FlatMapMain.onNext() [Thread Elastic N]
-> .... LambdaSubscriber.onNext("c") [Thread Elastic N]
-> ....
因此,您将看到 main 上的第一个 request(2) 然后是 elastic 上的 request(1) (因为一个内部已经完成,所以 FlatMap 将从上游请求另一个 1 个元素以满足并发需求)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.