JVM线程和Thread示例之间的关系

mwyxok5s  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(121)

我想我已经理解了操作系统线程和JVM线程之间的Map(首先我们有1 os:Many-green的“绿色线程”,然后有1:1Map,现在有jep-425,我们有M:NMap的虚拟线程:如果我错了,请纠正我)。然而,我对JVM线程和Thread示例之间的Map感到非常困惑:我几乎确定start()-艾德Thread示例和JVM线程之间存在1:1Map(如果我错了,请再次纠正我),但我不确定JVM线程是在构建Thread示例时创建的,还是仅在调用start()方法时才分配堆栈。无论正确答案是什么,我也想知道它是JVM/Java语言规范的一部分,还是实现,如OpenJDK。

kmbjn2e3

kmbjn2e31#

首先,你可以尝试创建许多Thread对象,然后尝试启动所有这些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},

  • 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实现。然而,在真正需要之前创建操作系统线程是愚蠢的。
我之所以称之为愚蠢的主要原因是资源管理。当你创建一个OS线程时,你也必须销毁它。当你start()一个Thread操作系统线程被创建,线程run()方法被执行,在该方法返回后,操作系统线程将被销毁。
如果一个假设的JVM实现已经在Thread构造函数中创建了OS线程,那么当Thread示例被垃圾收集时,它还需要某种方法来销毁该OS线程,这将是一个麻烦。

5ssjco0h

5ssjco0h2#

只有在调用start()方法时才创建Thread。你可以在这里的JDK文档中查看它:https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Thread.html
下面的代码向您展示了这是如何工作的

import java.util.Random;
public class Threads {

    private static final Random rnd = new Random();

    private static int rand(int a, int b) {
        synchronized (rnd) {
            return rnd.nextInt(b - a) + a;
        }
    }

    private static void loop() {
        while (true) {
            synchronized (rnd) {
                try {
                    Thread.sleep(rand(200, 1000));
                } catch (InterruptedException e) {}

                System.out.println("Hi, i'm ");
                System.out.println("thread #" + Thread.currentThread().getId());
            }
        }
    }

    public static class MyThread extends Thread {
        @Override
        public void run() {
            loop();
        }
    }

    public static void main(String[] args) {
        Thread t1 = new MyThread();
        t1.start();

        new Thread(Threads::loop).start();
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
        loop();

        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

}

字符串

相关问题