英文:
how heavy are Thread objects before they are started?
问题
我在想,在调用 start()
方法之前,Thread
的实例是否只是标准的Java对象,或者是否从它们创建的时刻起就分配了一些特殊的JVM/OS级别的资源(例如预分配的堆栈内存等)。根据初步研究,它们似乎像普通对象一样,但如果一些JVM专家能够确认这一点,那就太棒了。
我主要关心之前提到的线程堆栈内存,因为JVM规范中指出:“每个Java虚拟机线程都有一个私有的Java虚拟机堆栈,与线程同时创建”。我想知道这里的“创建”是指调用 start()
方法还是指创建一个 Thread
实例(我对操作系统线程、JVM线程和Thread
对象之间的确切关系不是很了解,所以感到困惑。此外,我想我可能听说过在过去几年里发生了一些变化,但我记不清具体是什么变化)。此外,我猜测,即使在创建Thread
实例的时候分配了一些操作系统虚拟内存,实际的物理内存页也只会在线程开始使用之后分配,而我再次猜测,只有在调用start()
方法之后才会开始使用线程。
这是我可能听说过的“变化”:jep-425 在java-19中引入。它将操作系统线程和JVM线程之间的映射更改为M:N。但是,我仍然不确定Thread
对象与JVM线程之间的映射(我几乎确定start()
方法启动的Thread
对象与JVM线程之间的映射是1:1,但不确定JVM线程是在Thread
实例创建时还是在start()
方法调用时创建的。我已经提出了另一个关于此问题的问题)。
英文:
I'm wondering whether before start()
method is called, instances of Thread
are merely a standard Java objects or if some special JVM/OS level resources are allocated right from the moment they are created (like for example pre-allocated memory for their stack etc). Based on a preliminary research, they seem like ordinary objects, but it would be awesome if some JVM experts could confirm this.
I'm mostly concerned regarding previously mentioned thread's stack memory, as the JVM spec states "Each Java Virtual Machine thread has a private Java Virtual Machine stack, created at the same time as the thread". I wonder if "created" here refers to a call to start()
method or a Thread
instance being constructed (I'm honestly not up2date with the exact relation between OS threads, JVM threads and Thread
objects, hence my confusion. Also I think I might have heard it changed a bit during last few years, but I can't recall exactly). Furthermore, I'm guessing, that even in the case some OS virtual memory is allocated at the moment a Thread
instance is constructed, actual physical memory pages for its stack will be allocated only after the thread starts to use, which, I guess again, is only after it is start()
-ed.
This is the "change I might have heard about": jep-425 introduced in java-19. It changes the mapping between OS threads and JVM threads to M:N. I'm however still not sure about the mapping between Thread
objects and JVM threads (I'm almost sure that mapping between start()
-ed Thread
objects and JVM threads is 1:1, but not sure if a JVM thread is created on Thread
instance creation or on start()
. I've asked another question regarding this)
答案1
得分: 3
尽管 Thread
构造函数进行了一些检查和初始化,但它不会将 Thread
实例绑定到本机操作系统线程。这只会在 Thread.start()
上发生,因此从这个意义上说,一个未启动的 Thread 不是一个“重”对象(我的意思是,它没有本机对等体)。
可能最昂贵的部分是,如果 Thread
构造函数设置为 inheritThreadLocals
为 true
(这在 Thread
的许多常见构造函数中发生),并且创建线程的线程在其映射中有很多线程局部值。
尽管如此,并且重申我对问题的评论,创建许多未启动的线程是不常见的,通常表示您正在做一些错误的事情(例如,扩展 Thread
而不是实现 Runnable
),您可能希望寻找替代方法。
英文:
Although the Thread
constructor does quite some checks and initialization, it will not bind the Thread
instance to a native OS thread. That will only happen on Thread.start()
, so in that sense an unstarted Thread is not a "heavy" object (by which I mean, it doesn't have a native peer).
Probably the most expensive part is if the Thread
is constructed with inheritThreadLocals
set to true
(which happens in a lot of the usual constructors of Thread
), and the creating thread has a lot of thread local values in its map.
That said, and reiterating the point of my comment on the question, creating a lot of threads without starting them is unusual, and generally indicates you're doing something wrong (e.g. extending Thread
instead of implementing Runnable
), you may want to look for alternatives.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论