我想我已经了解了操作系统线程和JVM线程之间的映射(首先,我们有1个OS:多个-绿色的"绿色线程",然后是1:1的映射,现在我们有了M:N映射的虚拟线程:如果我错了,请纠正我).然而,我对JVM线程和Thread实例之间的映射感到相当困惑:我可以肯定start()-ed Thread实例和JVM线程之间存在1:1的映射(同样,如果我说错了请纠正我),但我不确定是在构造Thread实例时创建JVM线程并分配其堆栈,还是仅在调用start()方法时才分配JVM线程.无论正确答案是什么,我也想知道它是JVM/Java语言规范的一部分,还是实现(如OpenJDK)的一部分.

推荐答案

首先,你可以通过创建多个Thread个对象来try 这一点,然后try 启动所有这些Thread对象:

public class ThreadRunner {
    public static void main(String[] args) {
        int maxThreads = 10_000_000;

        // Create Thread instances
        Thread[] threads = new Thread[maxThreads];
        Runnable r = () -> {
            try {
                Thread.sleep(1000_000);
            } catch (InterruptedException e) {
            }
        };
        for (int i = 0; i < maxThreads; i++) {
            threads[i] = new Thread(r);
        }

        // start Threads
        int count = 0;
        try {
            for (Thread t : threads) {
                t.start();
                count++;
                if (count % 1000 == 0) {
                    System.out.println(count);
                }
                Thread.yield();
            }
        } catch (OutOfMemoryError e) {
            System.out.println(count);
        }
    }
}

另一种方法是判断OpenJDK的源代码:

  • Thread.java调用本机start0()方法

  • Thread.c声明start0对于本机JVM_StartThread是未知的

 {"start0",           "()V",        (void *)&JVM_StartThread},
  • jvm.cpp包含本机函数,该函数确定本机线程的堆栈大小,然后使用

        jlong size =
               java_lang_Thread::stackSize(JNIHandles::resolve_non_null(jthread));
        // Allocate the C++ Thread structure and create the native thread.  The
        // stack size retrieved from java is 64-bit signed, but the constructor takes
        // size_t (an unsigned type), which may be 32 or 64-bit depending on the platform.
        //  - Avoid truncating on 32-bit platforms if size is greater than UINT_MAX.
        //  - Avoid passing negative values which would result in really large stacks.
        NOT_LP64(if (size > SIZE_MAX) size = SIZE_MAX;)
        size_t sz = size > 0 ? (size_t) size : 0;
        native_thread = new JavaThread(&thread_entry, sz);
    

这取决于具体的JVM实现吗?

原则上,这可能取决于特定的JVM实现.然而,在真正需要之前创建操作系统线程将是愚蠢的.

我说这很愚蠢的主要原因是资源管理.当您创建操作系统线程时,您还必须销毁它.当你start() a Thread操作系统线程被创建时,线程run()方法被执行,并且在该方法返回之后,操作系统线程将被销毁.

如果假设的JVM实现创建了Thread构造函数中已经存在的OS线程,那么当Thread实例被垃圾收集时,它还需要某种方法来销毁该OS线程,这将是很麻烦的.

Java相关问答推荐

使用json参数通过单击jSP文件中的按钮来运行server时出现问题

日食IDE 2024-03在Ubuntu下崩溃,导致hr_err_pid.log

使用包私有构造函数强制子类Java类

scanner 如何在执行hasNextLine一次后重新读取整个文件?

如何粘合(合并)文件Lucene?

ApachePOI:不带换行的新行

Java .类参数不通过构造函数传递

对某一Hyroby控制器禁用@cacheable

对于几乎不涉及逻辑的请求,您是否应该使用命令模式?

Java 21虚拟线程执行器的性能比池化操作系统线程的执行器差?

为什么JAVA&S清洁器使用链表而不是并发HashSet?

JPanel透支重叠的JComcoBox

将带有js文件的 bootstrap 程序导入maven项目时出错

多重延迟签名

如何让JavaFx应用程序识别依赖项?

SonarLint:只能有条件地调用方法(S)

如何在构建Gradle项目时排除com.google.guava依赖项的一个变体

当构造函数创建一个新实例时,Java为什么需要&new";

是否有一个Java Future实现可以在池繁忙时在调用者线程中执行?

Java泛型方法重载