Runtime.getRuntime().availableProcessors() 返回 JVM 可用的逻辑处理器数,即操作系统报告的可调度 CPU 单元数,通常等于物理核心数乘以超线程倍数,JDK 10+ 在容器中能准确反映 cgroup 限制后的值。

Runtime.getRuntime().availableProcessors() 返回的是逻辑处理器数,不是物理核心数
这个方法返回的是 JVM 可用的「逻辑处理器数量」,即操作系统报告给 Java 的可调度 CPU 单元数。在启用超线程(Hyper-Threading)的 x86 CPU 上,它通常返回 物理核心数 × 2;在某些容器或 cgroup 限制环境下,它可能返回被 cfs_quota_us 或 cpusets 限制后的值,而非宿主机真实物理核心数。
Java 标准库无法直接获取物理核心数
Java 没有提供跨平台 API 获取物理核心数。JVM 设计上只关心“可用并发执行单元”,因此 availableProcessors() 故意不区分物理/逻辑——它要的是线程调度上限,不是硬件拓扑。
- Windows 下可通过
GetLogicalProcessorInformation(需 JNI 或 JNA 调用)拿到RelationProcessorCore类型的组数 - Linux 下可读取
/sys/devices/system/cpu/cpu*/topology/core_id并去重统计(注意:需 root 权限才能访问部分路径,且容器中常被挂载为只读或屏蔽) - macOS 下需调用
sysctlbyname("hw.physicalcpu")
常见误用场景和替代思路
很多开发者想用物理核心数来“精确控制线程池大小”,但这是个伪需求——ForkJoinPool、Executors.newFixedThreadPool 等默认都基于 availableProcessors(),恰恰是因为逻辑核数更能反映实际并行吞吐能力(尤其 I/O 密集型任务中,超线程带来的上下文切换收益明显)。
- 若你真在做 CPU 密集型计算且确认超线程带来负优化(极少见),应通过启动参数显式限制:如
-XX:ActiveProcessorCount=4(JDK 10+),让 JVM 自己“假装”只有 4 个可用核 - 避免自己解析
/proc/cpuinfo:字段含义不统一(cpu cores在多 socket 机器上只表示单颗 CPU 的核心数)、容器中不可靠、Android/Linux 内核版本差异大 - 不要缓存
availableProcessors()结果:它在容器热缩容时可能变化(如 Kubernetes 动态调整resources.limits.cpu后触发 cgroup 更新)
真正需要物理核心数时的务实做法
除非你在写硬件监控工具、调度器内核模块或性能调优报告,否则大概率不需要它。如果必须获取:
立即学习“Java免费学习笔记(深入)”;
- 优先查系统文档:Kubernetes 中用
status.capacity.cpu、Docker 用docker info | grep 'CPUs',比从 Java 进程里硬挖更可靠 - 用
System.getProperty("os.name")分支 + JNA 加载对应系统 API(例如com.sun.jna.platform.win32.WinNT或com.sun.jna.platform.unix.UnixLibC),但要接受 Windows/Linux/macOS 三端不同实现 - 接受近似值:对 Intel CPU,可读取
/proc/cpuinfo中core id去重;但注意 Docker 默认不挂载/proc全路径,需加--privileged或显式绑定挂载
物理核心数不是“更准确”的指标,而是“更难获取且用途狭窄”的指标。多数生产级并发控制逻辑,老老实实用 Runtime.getRuntime().availableProcessors() 就够了——它返回的本来就是 JVM 认为“此刻该用几个线程并行干活”的答案。


















