首页 > 解决方案 > 当我们有多个 Java 线程时,运行时会发生什么?

问题描述

我试图了解当您有多个线程对象并在它们上调用 start 时会发生什么。

为此,我编写了以下代码:

public class Testing {
    public static void main(String[] args) {
        for(int i =0; i <100; i++){
            (new TestThread()).start();
        }
    }
}

class TestThread extends Thread {
    @Override
    public void run() {
        System.out.println("Thread instance: " + Thread.currentThread().getName());
    }
}

所以我得到的输出涉及 Thread-x,其中 x 是从 0 到 99,但它们的顺序与自然顺序不同(即 0、1、2、3、...)。我预料到了这一点,因为我读到我们无法控制这些线程运行时会发生什么,但我想要求澄清运行时究竟发生了什么。

是不是主线程经历了创建这些线程的所有 100 次 for 循环迭代,然后 JVM 稍后任意决定这些 Thread 对象中的每一个何时启动?

谢谢。

标签: javamultithreading

解决方案


我想要求澄清运行时到底发生了什么。

实际发生的是,当您调用 时start(),JVM通常1对操作系统进行系统调用以执行以下操作:

  1. 为新的线程堆栈分配内存段。(通常分配两个段:一个段用于线程堆栈,第二个只读段用于检测堆栈溢出。)

  2. 创建一个新的本地线程2

创建本机线程时,它必须等待(与所有其他当前准备运行的线程一起)操作系统的线程调度程序将其调度到物理内核。一般来说,操作系统的线程调度器尊重优先级,但相同优先级的线程之间的调度通常不是“公平的”;即不保证“先到先得”。

因此,在某些时候,操作系统将安排新的本机线程运行。发生这种情况时,线程将执行一些获取Runnable引用并调用其run()方法的本机代码。相同的代码将处理该run()方法中任何未捕获的异常。

确切的细节将是特定于 JVM 和特定于操作系统的,您实际上不需要知道它们。


是不是主线程经历了创建这些线程的所有 100 次 for 循环迭代,然后 JVM 稍后任意决定这些 Thread 对象中的每一个何时启动?

不必要。它可能会,也可能不会。

实际发生的情况将取决于操作系统的本机代码调度程序如何处理新创建的本机线程。这将取决于各种难以预测的因素。例如,其他线程和其他应用程序的行为等等。

基本上,不能保证3子线程将以任何特定顺序开始执行,或者主线程将或不会在任何子线程启动之前完成循环。


1 - 这对于在 Java 线程和本机线程之间提供 1 对 1 映射的 JVM 来说很典型。这是当前大多数 JVM 的行为方式,但它不是唯一的实现模型。
2 - 本机线程是操作系统支持的线程。有关更多信息,请参阅Java 线程模型,有关示例,请参阅本机 POSIX 线程库。
3 - 在某些平台和负载条件下,您可能能够观察到行为模式,但您可能会发现其他平台上的行为有所不同等。


推荐阅读