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