繁体   English   中英

flatMap 如何管理线程?

[英]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)

问题:

  1. 为什么flatMapmain线程请求 2 个元素,然后从其他线程请求更多元素?

  2. 为什么subscribe不由main线程处理?

为什么 2 从主线程请求?

第一个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机制的驱动程序。 FlatMapInnerFlatMapMain之间的交互正在通过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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM