
java 线程本质上是**并发的**,在多核系统上可自然实现**并行执行**;jvm 本身不强制并行,但现代 jdk(包括 1.7+)通过 os 级线程映射和内核调度,使 `thread`、`forkjoinpool` 和 `threadpoolexecutor` 均能在多核环境下真正并行运行。
在 Java 中,“并发(concurrent)”与“并行(parallel)”并非互斥概念,而是存在包含关系:所有并行执行必然是并发的,但并发执行未必是并行的。
- ✅ 并发(Concurrent):指多个线程的逻辑执行流在时间上重叠(interleaved),其事件发生顺序未严格定义(如无显式同步),强调“看起来同时进行”,依赖操作系统调度器在单核或多核上切换执行权。
- ✅ 并行(Parallel):特指多个线程在同一时刻被物理调度到不同 CPU 核心(或硬件线程) 上真正同时执行,需满足:多核硬件 + 支持抢占式多任务的操作系统 + JVM 将 Java 线程一对一映射为 OS 线程(即 1:1 模型)。
自 Java 早期版本(JDK 1.2 起)起,主流 JVM(如 HotSpot)就已采用 1:1 线程模型:每个 java.lang.Thread 实例均对应一个由操作系统内核管理的原生线程(POSIX pthread 或 Windows thread)。这意味着:
- 在单核系统上 → 线程表现为纯并发(时间片轮转,交替执行);
- 在多核系统上 → 线程可被 OS 调度器分发至不同核心 → 实现真正的并行(前提是无强竞争、无阻塞、资源充足)。
? 关于 “Java 1.7 开始 ‘core-aware’” 的常见误解: JDK 1.7 并未引入新的线程模型,也未新增“感知核心”的底层机制。所谓“core-aware”实为对 JVM 内部优化(如 ForkJoinPool 默认并行度设为 Runtime.getRuntime().availableProcessors())、垃圾收集器(如 G1 对多核更友好)及类库(如 Arrays.parallelSort()、Stream.parallel())的统称。线程能否并行,始终取决于 OS 调度能力,而非 JDK 版本本身。
各线程执行载体的实际行为对比
| 组件 | 是否并发 | 是否并行(多核下) | 关键说明 |
|---|---|---|---|
| new Thread(...).start() | ✅ 是 | ✅ 是(条件满足时) | 直接创建 OS 线程,完全交由 OS 调度;无内置核心绑定策略,但现代 Linux/Windows 调度器天然支持跨核负载均衡。 |
| ThreadPoolExecutor(含 Executors.newFixedThreadPool(n)) | ✅ 是 | ✅ 是 | 底层仍使用普通 Thread;若线程数 ≤ 可用核心数且任务无阻塞,高概率并行执行;注意:CachedThreadPool 创建的空闲线程可能被 OS 迁移,非绑定核心。 |
| ForkJoinPool(默认构造 / commonPool()) | ✅ 是 | ✅ 是(且更智能) | 默认并行度 = availableProcessors();内置工作窃取(work-stealing)机制,动态平衡多核负载;parallelStream() 和 CompletableFuture 默认使用它,是 Java 并行编程的推荐基础设施。 |
示例:验证并行执行(Linux/macOS 下)
public class ParallelCheck {
public static void main(String[] args) throws InterruptedException {
int cores = Runtime.getRuntime().availableProcessors();
System.out.println("Available processors: " + cores);
// 启动 cores 个计算密集型线程
List threads = new ArrayList<>();
for (int i = 0; i < cores; i++) {
Thread t = new Thread(() -> {
long sum = 0;
// 模拟 CPU 密集型任务(避免 I/O 阻塞干扰)
for (long j = 0; j < 10_000_000_000L; j++) {
sum += j & 1;
}
System.out.println(Thread.currentThread().getName() + " finished, sum=" + sum);
}, "Worker-" + i);
threads.add(t);
t.start();
}
for (Thread t : threads) t.join();
System.out.println("All threads completed.");
}
} ✅ 在 4 核机器上运行此程序,通过 top -H 或 htop 观察线程 CPU 占用率,可清晰看到多个 Worker-* 线程同时接近 100% 占用不同核心,证实并行性。
注意事项与最佳实践
- ⚠️ 不要假设线程必然并行:即使有多核,若任务含频繁锁竞争、I/O 阻塞、GC 暂停或 OS 调度压力大,并行度会显著下降。
- ⚠️ 避免过度创建线程:new Thread() 无复用机制,高并发场景应优先选用 ThreadPoolExecutor 或 ForkJoinPool。
- ⚠️ ForkJoinPool.commonPool() 有全局共享限制:其大小受 java.util.concurrent.ForkJoinPool.common.parallelism 系统属性控制(默认 = availableProcessors() - 1),不适合长期阻塞任务(应创建专用池)。
- ✅ 推荐并行编程模式:
// 更安全、声明式、自动适配硬件的并行方式 int[] arr = new int[1_000_000]; Arrays.parallelSetAll(arr, i -> i * 2); // 并行填充 Arrays.parallelSort(arr); // 并行排序 Arrays.stream(arr).parallel().filter(x -> x > 500_000).count(); // 并行流
总之,Java 线程模型从诞生之初就是面向并发设计的,而并行只是其在多核硬件上的自然延伸。开发者无需纠结“JDK 版本是否支持并行”,而应关注:合理建模任务、选择合适执行器、减少共享竞争、善用现代 API——这才是释放多核性能的关键。
立即学习“Java免费学习笔记(深入)”;










