使用ThreadPoolExecutor时CPU密集型任务无明显上下文切换开销的疑问
CPU密集型任务线程池大小实验:为何线程数超过核心数后执行时间未显著增加?
我正在开展一项简单实验,旨在确定处理大量CPU密集型任务时的最优线程池大小。我已知理论上该大小应等于机器核心数,但希望通过实证验证这个结论。
实验环境
- 设备:2017款MacbookPro
- CPU:3.1GHz Intel Core i5,2个物理核心,开启超线程后共4个逻辑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毫秒,我认为这个时长足够让线程调度器至少完成一次抢占操作。
实验结果(多次运行取平均值)
- 线程池大小1:57秒
- 线程池大小2:29秒
- 线程池大小4:18秒
- 线程池大小8:18.1秒
- 线程池大小16:18.2秒
- 线程池大小32:17.8秒
- 线程池大小64:18.2秒
我的疑问
我原本预期当线程数超过CPU核心数(这里是4个逻辑CPU)时,频繁的上下文切换会带来额外开销,导致执行时间显著增加,但实际结果却显示,线程数超过4之后,执行时间几乎没有变化。我用VisualVM监控程序时,看到所有线程都已创建且处于运行状态,CPU使用率接近95%。
请问我在实验设计或者理解上忽略了什么?
内容的提问来源于stack exchange,提问作者Cosmin Ioniță
相关产品推荐
相关产品推荐

