为什么创建线程被认为是昂贵的?
因为它>><<昂贵。
Java线程的创建成本很高,因为涉及相当多的工作:
- 必须为线程堆栈分配和初始化一个大的内存块。
- 需要进行系统调用以创建/注册主机操作系统的本机线程。
- 需要创建、初始化描述符并将其添加到 JVM 内部数据结构中。
从某种意义上说,它也很昂贵,因为只要线程处于活动状态,它就会束缚资源;例如,线程堆栈,可以从堆栈访问的任何对象,JVM线程描述符,操作系统本机线程描述符。
所有这些事情的成本都是特定于平台的,但是在我遇到过的任何Java平台上,它们都不便宜。
谷歌搜索发现了一个旧的基准测试,它报告在运行2002年老式Linux的2002年老式双处理器Xeon上的Sun Java 1.4.1上的线程创建速率约为每秒4000次。一个更现代化的平台将提供更好的数字...我不能评论方法论...但至少它为线程创建可能有多昂贵提供了一个大概。
Peter Lawrey的基准测试表明,从绝对值来看,这些天线程的创建速度要快得多,但目前尚不清楚其中有多少是由于Java和/或操作系统的改进......或更高的处理器速度。但他的数字仍然表明,如果你使用线程池而不是每次创建/启动一个新线程,则改进了150倍以上。(他指出,这都是相对的...)
以上假设是本机线程而不是绿色线程,但出于性能原因,现代 JVM 都使用本机线程。创建绿色线可能更便宜,但您在其他领域需要付费。
更新:OpenJDK Loom项目旨在为标准Java线程提供轻量级的替代方案。他们提出了虚拟线程,它们是本机线程和绿色线程的混合体。简单来说,虚拟线程更像是绿色线程实现,当需要并行执行时,它使用下面的本机线程。
截至目前(2021年1月),Project Loom的工作仍处于原型设计阶段,(AFAIK)没有针对该版本的Java版本。
我做了一些挖掘,看看Java线程的堆栈是如何真正分配的。在 Linux 上的 OpenJDK 6 中,线程堆栈由创建本机线程的调用分配。(JVM 不传递预分配的堆栈。pthread_create
pthread_create
然后,在堆栈中通过调用分配,如下所示:pthread_create
mmap
mmap(0, attr.__stacksize,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0)
根据 ,该标志导致内存初始化为零。man mmap
MAP_ANONYMOUS
因此,即使新的Java线程堆栈可能不必归零(根据JVM规范),但在实践中(至少在Linux上的OpenJDK 6中),它们被清零。