Rx java 不同处理时间下flatMap和parallel的并发行为差异

Rx java 不同处理时间下flatMap和parallel的并发行为差异,rx-java,rx-java2,Rx Java,Rx Java2,我在以下两条管道中看到了不同的行为,我希望它们相似/相同。其目的是处理并发级别为x(示例中为4)的项,而不是阻止任何项在“缓冲区”中处理 我在这里重新创建了一个场景,使用Flowable.range(11280)作为源代码,并对2项模拟一些“缓慢处理”,只会阻塞5秒钟 Flowable.range(11280)//可冷流动,物料“按需”生产 .doOnNext{logEvent(“producted$it”)} .parallel(4,1)//parallism为4,prefetch为1 .ru

我在以下两条管道中看到了不同的行为,我希望它们相似/相同。其目的是处理并发级别为x(示例中为4)的项,而不是阻止任何项在“缓冲区”中处理

我在这里重新创建了一个场景,使用
Flowable.range(11280)
作为源代码,并对
2
项模拟一些“缓慢处理”,只会阻塞5秒钟

Flowable.range(11280)//可冷流动,物料“按需”生产
.doOnNext{logEvent(“producted$it”)}
.parallel(4,1)//parallism为4,prefetch为1
.runOn(Schedulers.computation(),1)//再次使用1的预取
.doOnNext(::进程)

.doOnNext{logEvent(“用$it完成”)}
.ignoreElements()
.blockingaway()
为此,我得到如下输出:

...
2021-04-12T12:15:49.147 - [main] produced 4
2021-04-12T12:15:49.147 - [main] produced 5
2021-04-12T12:15:49.147 - [RxComputationThreadPool-2] slow processing 2
2021-04-12T12:15:49.147 - [RxComputationThreadPool-4] fast processing 4
...
2021-04-12T12:15:49.170 - [RxComputationThreadPool-1] fast processing 1278
2021-04-12T12:15:49.170 - [RxComputationThreadPool-1] done with 1278
2021-04-12T12:15:54.147 - [RxComputationThreadPool-2] slow processing 2 done
2021-04-12T12:15:54.147 - [RxComputationThreadPool-2] done with 2
在这种情况下,每个线程处理的项目数细分如下:

RxComputationThreadPool-2: 1
RxComputationThreadPool-4: 429
RxComputationThreadPool-3: 416
RxComputationThreadPool-1: 434
还要注意日志中的时间,除2外的所有项目均在1秒内处理,项目2按预期在5秒后完成

现在,我希望通过这种平面图方法实现类似的行为:

可流动范围(11280)
.doOnNext{logEvent(“producted$it”)}
.flatMapSingle({Single.fromCallable{process(it);it}.subscribeOn(Schedulers.computation())},
true,4)//delayErrors(true或false无关紧要)和maxConcurrency
.doOnNext{logEvent(“用$it完成”)}
.ignoreElements()
.blockingaway()
但是,我得到如下输出:

...
2021-04-12T12:29:24.452 - [main] produced 4
2021-04-12T12:29:24.454 - [RxComputationThreadPool-1] fast processing 1
2021-04-12T12:29:24.454 - [RxComputationThreadPool-3] fast processing 3
2021-04-12T12:29:24.455 - [RxComputationThreadPool-1] done with 1
2021-04-12T12:29:24.455 - [RxComputationThreadPool-2] slow processing 2
2021-04-12T12:29:24.455 - [RxComputationThreadPool-1] produced 5
...
2021-04-12T12:29:24.458 - [RxComputationThreadPool-8] produced 25
2021-04-12T12:29:24.459 - [RxComputationThreadPool-1] fast processing 25
2021-04-12T12:29:24.459 - [RxComputationThreadPool-1] done with 25
2021-04-12T12:29:24.459 - [RxComputationThreadPool-1] produced 26
2021-04-12T12:29:29.455 - [RxComputationThreadPool-2] slow processing 2 done
2021-04-12T12:29:29.455 - [RxComputationThreadPool-2] done with 2
2021-04-12T12:29:29.455 - [RxComputationThreadPool-2] produced 27
2021-04-12T12:29:29.455 - [RxComputationThreadPool-2] fast processing 10
...
2021-04-12T12:29:29.477 - [RxComputationThreadPool-1] produced 1280
2021-04-12T12:29:29.477 - [RxComputationThreadPool-7] fast processing 1279
2021-04-12T12:29:29.477 - [RxComputationThreadPool-8] fast processing 1280
2021-04-12T12:29:29.477 - [RxComputationThreadPool-1] done with 1278
2021-04-12T12:29:29.477 - [RxComputationThreadPool-1] done with 1279
2021-04-12T12:29:29.477 - [RxComputationThreadPool-1] done with 1280
RxComputationThreadPool-3: 160
RxComputationThreadPool-4: 160
RxComputationThreadPool-5: 160
RxComputationThreadPool-7: 160
RxComputationThreadPool-2: 160
RxComputationThreadPool-6: 160
RxComputationThreadPool-1: 160
RxComputationThreadPool-8: 160
每个线程处理的项目数的细分始终是这样均匀分布的:

...
2021-04-12T12:29:24.452 - [main] produced 4
2021-04-12T12:29:24.454 - [RxComputationThreadPool-1] fast processing 1
2021-04-12T12:29:24.454 - [RxComputationThreadPool-3] fast processing 3
2021-04-12T12:29:24.455 - [RxComputationThreadPool-1] done with 1
2021-04-12T12:29:24.455 - [RxComputationThreadPool-2] slow processing 2
2021-04-12T12:29:24.455 - [RxComputationThreadPool-1] produced 5
...
2021-04-12T12:29:24.458 - [RxComputationThreadPool-8] produced 25
2021-04-12T12:29:24.459 - [RxComputationThreadPool-1] fast processing 25
2021-04-12T12:29:24.459 - [RxComputationThreadPool-1] done with 25
2021-04-12T12:29:24.459 - [RxComputationThreadPool-1] produced 26
2021-04-12T12:29:29.455 - [RxComputationThreadPool-2] slow processing 2 done
2021-04-12T12:29:29.455 - [RxComputationThreadPool-2] done with 2
2021-04-12T12:29:29.455 - [RxComputationThreadPool-2] produced 27
2021-04-12T12:29:29.455 - [RxComputationThreadPool-2] fast processing 10
...
2021-04-12T12:29:29.477 - [RxComputationThreadPool-1] produced 1280
2021-04-12T12:29:29.477 - [RxComputationThreadPool-7] fast processing 1279
2021-04-12T12:29:29.477 - [RxComputationThreadPool-8] fast processing 1280
2021-04-12T12:29:29.477 - [RxComputationThreadPool-1] done with 1278
2021-04-12T12:29:29.477 - [RxComputationThreadPool-1] done with 1279
2021-04-12T12:29:29.477 - [RxComputationThreadPool-1] done with 1280
RxComputationThreadPool-3: 160
RxComputationThreadPool-4: 160
RxComputationThreadPool-5: 160
RxComputationThreadPool-7: 160
RxComputationThreadPool-2: 160
RxComputationThreadPool-6: 160
RxComputationThreadPool-1: 160
RxComputationThreadPool-8: 160
在这里,请注意
生成26
缓慢处理2完成之间的时间间隔,事实上,处理26的“单个”直到2完成处理才创建,即使它是唯一正在处理的项目

即使将
maxConcurrency
设置为4,为什么在使用flatMap时处理1个项目会阻止处理其他项目?

上述实用程序仅供参考:

数据类事件(val-thread:thread,val-timeMillis:Long,val-msg:String){
val localTime:LocalDateTime by lazy(LazyThreadSafetyMode.NONE){
Instant.ofEpochMilli(timeMillis).atZone(ZoneId.systemDefault()).toLocalDateTime()
}
重写fun-toString():String=“${localTime}-[${thread.name}]$msg”
}
val事件:ConcurrentLinkedQue=ConcurrentLinkedQue()
趣味日志事件(消息:字符串){
添加(事件(Thread.currentThread(),System.currentTimeMillis(),msg))
}
val countsByThread:ConcurrentMap=ConcurrentHashMap()
有趣的过程(it:Int){
val thread=thread.currentThread()
countsByThread.compute(线程){{,prev->if(prev!=null)prev+1 else 1}
如果(it==2){
logEvent(“缓慢处理$it”)
线程。睡眠(5_000)
logEvent(“缓慢处理$it done”)
}否则{
logEvent(“快速处理$it”)
}
}

Rxjava2 2.2.21版

通过
并行
设置,您可以获得固定数量的导轨,这些导轨在运行过程中需要更多的项目。由于只有一条轨道被困的时间更长,其他3条轨道可以请求并得到服务


使用
flatMap
设置,以循环方式将每个项目分配给
调度器
item-1-Scheduler-1item-2-Scheduler-2,…,item-5-Scheduler-1item-6-Scheduler-2。如果项-N使调度程序陷入困境,则项-(N+4)项-(N+8)等将等待项-N完成。因此,例如,当项目5-scheduler-1完成时,下一个项目将被分配给被阻止的计划程序-2。在几个项目之后,所有4个活动项目都将等待调度器-2

,因此基本上,
flatMap
安装程序以最大
maxConcurrency
,一次一组的大小同时处理项目?Nvm,我需要更好地理解调度程序是如何发挥作用的,因为我看到了计算与io的不同行为,尽管两者产生的线程数几乎相同(io实际上更少)。计算有固定的工作线程池,默认数量是核心计数。上面的示例假设一个4工作调度器,但是一个8工作调度器会出现同样的问题。io调度器缓存工作线程,并在运行时重用它们,因此在上面的示例中,工作线程陷入困境,但随后会创建一个新的工作线程来为后续项目提供服务。