new Thread显著降低L1/L2缓存命中率,因其放弃线程位置控制,导致核心间无序迁移引发缓存反复失效、伪共享加剧及JIT优化退化。

直接用 new Thread 启动线程,在高并发热点代码中会显著拉低 L1/L2 缓存命中率,核心原因不是“创建线程慢”,而是它彻底放弃了对线程执行位置的控制——导致线程在 CPU 核心间无序漂移,反复冲刷已预热的私有缓存。
线程无绑定 → 缓存反复失效
每个 CPU 核心的 L1 和 L2 缓存是独享的。当一个线程在核心 0 上运行一段时间后,它的指令、局部变量、热点对象(如循环变量、临时数组)已大量驻留在该核心的 L1/L2 中。一旦操作系统调度器把该线程迁移到核心 3,它原先在核心 0 缓存里的所有数据立即失效,必须重新从 L3 或主存加载——这个过程耗时远高于缓存命中(L1 延迟约 1ns,主存约 100ns)。new Thread 不设置亲和性,完全交由 OS 动态调度,频繁迁移在高并发下成为常态。
对象分配加剧缓存行污染
Java 中 new Thread 本身就会触发对象分配:Thread 对象、其内部的栈空间、InheritableThreadLocal 副本等。这些分配集中在堆上某一段内存,而 JVM 的 TLAB(Thread Local Allocation Buffer)默认按线程隔离,但若未绑定核心,不同线程的 TLAB 可能被分配到同一缓存行附近。多个线程在不同核心上写入相邻地址,极易引发伪共享(False Sharing),进一步触发 MESI 协议广播、缓存行无效化,L1/L2 命中率雪崩式下降。
JIT 优化退化加重缓存压力
HotSpot JIT 针对长期稳定运行的热点方法做深度优化(如循环展开、标量替换、寄存器分配)。但 new Thread 启动的线程生命周期短、执行路径不连续、核心不固定,JIT 很难将其识别为“稳定热点”,往往停留在 C1 编译或解释执行阶段。未优化的字节码执行效率低、访存模式差,单位时间内触发更多缓存未命中,形成恶性循环。
正确做法:用线程池 + 亲和性绑定
- 用
ThreadPoolExecutor复用线程,避免高频创建销毁; - 配合
AffinityLock(如 Java-Thread-Affinity 库)或pthread_setaffinity_np(JNI 封装)将工作线程长期绑定至特定逻辑核心; - 关键计算类尽量使用
@Contended隔离字段,防止伪共享; - 对极致场景,可配合 JVM 参数
-XX:+UseNUMA和-XX:NUMAInterleavingRatio优化内存本地性。


















