簡體   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