单核机器上的 CompletableFuture
Posted
技术标签:
【中文标题】单核机器上的 CompletableFuture【英文标题】:CompletableFuture on Single core machine 【发布时间】:2020-10-21 14:44:40 【问题描述】:我有 Kafka 消费者生产应用程序,它使用一条消息并将其分成 3 个部分,并调用两个 Rest API 和一个 SOAP WS。目前这些是一个接一个地连续调用的,它们本质上是相互独立的,理想情况下应该是异步的。
Kafka 消费者也部署在具有 1 个核心的 Azure 小型 VM 上,链接相同 Azure VMs。
我打算使用CompletableFuture
的supplyAsync()
,但为此我可以选择下面提到的两个选项之一
-
使用大小为 3 的自定义
Threadpool
或
使用forkjoin
池
既然我有一个单核机器,应该选择哪一个,为什么? CompletableFuture
也适用于单核机吗?
【问题讨论】:
当然,你可以使用CompletableFuture
; Java 的并发性与其他任何东西一样高级,并且从运行它的实际机器中抽象出来。这意味着,即使它实际上可以并行处理,JVM 也将自行安排其任务或仅按看起来合适的方式处理它 - 这可能是顺序的,但对于自定义线程或 forkjoin 池也是如此。跨度>
奇怪的是,CompletableFuture
is specified as“All 异步 方法的行为没有显式 Executor 参数是使用 ForkJoinPool.commonPool()
执行的(除非它不支持至少两个并行级别,在这种情况下,会创建一个新线程来运行每个任务)。”因此,在单核机器上,您至少可以获得更多并行度从线程数的角度。因此建议使用显式执行器。一个 fork/join 池是一个线程池。
@Holger 在单核机器中,fork join 普通池不是只有一个核吗(Runtime.getAvailableProcessors() 将返回 1),这意味着只有一个线程将被执行时间?如果是,那么使用 CompleteableFuture 没有任何意义。
正如文档所说,当公共池的并行度小于两个时,CompletableFuture
不使用公共池,而是为每个任务创建一个新线程。你可以从字面上理解它;然后它确实做到了new Thread(…)
,而无需使用任何执行程序服务。这就是为什么我建议在这种情况下使用具有合理配置的显式执行器。它可以是普通线程池,也可以是具有明确指定并行度的自定义 fork/join 池。
【参考方案1】:
您可以毫无问题地在单线程 cpu 上使用并发,但它只会对您的程序结构有益,而不是性能。
Kafka 为 CompletableFuture
1 类型 - KafkaFuture
2 提供了它自己的 shim,您可能想改用它。
【讨论】:
以上是关于单核机器上的 CompletableFuture的主要内容,如果未能解决你的问题,请参考以下文章
在多线程应用程序表单上使用while循环锁定c#阻塞单核机器上的所有线程