【发布时间】:2021-03-29 22:12:22
【问题描述】:
我正在尝试做一个简单的实验,当你有一堆 CPU 密集型任务时,我想找出合适的线程池大小。
我已经知道这个大小应该等于机器上的核心数,但我想通过经验来证明这一点。代码如下:
public class Main {
public static void main(String[] args) throws ExecutionException {
List<Future> futures = new ArrayList<>();
ExecutorService threadPool = Executors.newFixedThreadPool(4);
long startTime = System.currentTimeMillis();
for (int i = 0; i < 100; i++) {
futures.add(threadPool.submit(new CpuBoundTask()));
}
for (int i = 0; i < futures.size(); i++) {
futures.get(i).get();
}
long endTime = System.currentTimeMillis();
System.out.println("Time = " + (endTime - startTime));
threadPool.shutdown();
}
static class CpuBoundTask implements Runnable {
@Override
public void run() {
int a = 0;
for (int i = 0; i < 90000000; i++) {
a = (int) (a + Math.tan(a));
}
}
}
}
每个任务在大约 700 毫秒内执行(我认为这足以被 ThreadScheduler 抢占至少一次)。
我在 MacbookPro 2017、3.1 GHz Intel Core i5、2 个激活超线程的物理内核、4 个逻辑 CPU 上运行此程序。
我调整了线程池的大小,并多次运行该程序(平均时间)。结果如下:
1 thread = 57 seconds
2 threads = 29 seconds
4 threads = 18 seconds
8 threads = 18.1 seconds
16 threads = 18.2 seconds
32 threads = 17.8 seconds
64 threads = 18.2 seconds
由于上下文切换开销,我预计执行时间会显着增加,一旦我添加了这么多线程(超过 CPU 内核的数量),但似乎这并没有真正发生。
我使用 VisualVM 监控程序,并且看起来所有线程都已创建并且它们处于运行状态,正如预期的那样。此外,CPU 似乎使用得当(接近 95%)。
我有什么遗漏的吗?
【问题讨论】:
标签: java multithreading performance parallel-processing threadpool