起因
最近针对线程池的核心线程数设置多少与同事发生了一些歧义:
我的理论依据是大厂面试中面试题和标准答案(曾经被虐过!):CPU密集型设置CPU核心数 + 1;IO密集型CPU核心数 * 2(可以远大于核心数)。
其他人说实际开发中并没有人会在意这些设置多少无所谓,我觉得这实在是无法接受。
于是我做了一波测试分别针对CPU密集型和IO密集型来看核心线程数和最大线程数对执行时间的影响。
最终结论
但很多面试题中说的:“CPU密集型核心线程数过大超过CPU核心数那么执行时间反而会更久”。其实是不对的,应该是CPU密集型核心线程数过大超过CPU核心数那么执行时间可能会出现波动较大的情况不稳定,原因可能是:
GC / JIT / cache / context switch。
过程结论
CPU密集型任务结论是:
- 线程上下文切换造成的开销其实并没有想象中那么大。
- CPU密集型耗费时间情况:

线程数 < 核心数:执行速度 吞吐能力线性上升
线程数 ≈ 核心数:执行速度 达到峰值(最快)
线程数 > 核心数:
出现上下文切换 + cache miss + 调度竞争
执行速度 吞吐能力进入瓶颈不会有显著提升出现吞吐能力的抖动(不稳定可能会出现大于1.5倍~2倍的平均执行速度)
猜测不稳定因素:GC / JIT / cache / context switch
实验参数:
- 核心线程数和最大线程数都是从1~300变化,不同的线程数执行10次子线程任务。
- 每个子线程执行200_000_000L次Math.sqrt(i)。
IO密集型任务结论是:

- 线程上下文切换造成的开销其实并没有想象中那么大。
- 线程越大→ 性能快速提升 → 达到平台期 → 不再变化。
实验参数:
- 核心线程数和最大线程数都是从1~300变化,不同的线程数执行10次子线程任务。
- 每个子线程执行Thread.sleep(200)
代码:
package com.luology.test.test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Test {
public static void main(String[] args) throws Exception {
int cpu = Runtime.getRuntime().availableProcessors();
System.out.println("CPU核心数:" + cpu);
for (int threadNum = 1; threadNum <= 300; threadNum++) {
test(threadNum);
}
}
private static void test(int threadNum)
throws Exception {
ExecutorService pool = Executors.newFixedThreadPool(threadNum);
long start = System.currentTimeMillis();
List<Future<Long>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
futures.add(pool.submit(
new CpuTask(100000)
));
}
for (Future<Long> future : futures) {
future.get();
}
long end = System.currentTimeMillis();
pool.shutdown();
System.out.printf(
"线程数=%d,耗时=%dms%n",
threadNum,
end - start
);
}
}
package com.luology.test.test;
import java.util.concurrent.Callable;
public class CpuTask implements Callable<Long> {
private final int num;
public CpuTask(int num) {
this.num = num;
}
@Override
public Long call() throws InterruptedException {
// ### CPU密集型任务
// double sum = 0;
//
// for (long i = 0; i < 200_000_000L; i++) {
// sum += Math.sqrt(i);
// }
//
// return (long) sum;
// ### IO 密集型任务
Thread.sleep(200);
return 1L;
}
}

1万+

被折叠的 条评论
为什么被折叠?



