Java中的线程池执行器

3
ExecutorService threadPool = Executors.newFixedThreadPool(N);

for (Runnable task : tasks) {
    threadPool.execute(task);
}

我对多线程还有些陌生。这是我最近在面试中遇到的问题。能否帮我找到答案并给出明确的解释呢? 在上面的代码中,每个任务花费25%的时间进行计算,75%的时间进行I/O操作。假设使用一个四核机器(没有超线程),为了实现最佳性能而不浪费线程,线程池N的大小应该是多少,假设I/O容量无限。

2个回答

1
如果您的机器具有无限I/O,那么您可以完全集中于CPU。每个任务在运行时使用四分之一的CPU。这意味着您可以运行四个任务来饱和一个CPU核心,这使得在四核机器上N=16。
然而,这只是一个纯理论的答案。在现实中,您会发现许多问题,为什么N=16可能太大或太小。例如,假设所有16个任务在调度(CPU vs IO)方面都是相同的,并且在同一时刻启动。这意味着,在第一个CPU密集时间段内,执行速度降低到四分之一(16个线程正在争夺四个CPU)。此外,人们会认为,运行操作系统、调度程序、垃圾收集等需要一定量的CPU负载。这将使N=16过大。
另一方面,如果不要求每个任务以最大的单独速度运行,则更大的N可能会给您带来更好的整体性能,例如,如果在某个时间段超过3/4的线程正在进行I/O,则会在该时刻留下未使用的CPU资源。
我假设这不是面试问题的重点,但这是在现实世界中需要考虑的事情。

1
如果IO不是制约因素(由于IO容量无限),您可以集中精力关注可用的核心数量。
ExecutorService threadPool = Executors.newFixedThreadPool(
                             Runtime.getRuntime().availableProcessors());

如果您在Executors中使用newWorkStealingPool(从Java 8版本开始),性能将进一步提高。

public static ExecutorService newWorkStealingPool()

使用所有可用的处理器作为目标并行级别,创建一个工作窃取线程池。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接