1

在下面的代码段中,我创建了 3 个线程并给它们一个数字来跟踪哪个是哪个。当我执行程序时,除了线程是随机排序的之外,输出与预期的一样。我本来希望它们以与创建和启动相同的顺序出现(1-2-3),但每次我都会得到一个乱码。

为什么是这样?

一个PrintTask对象创建一个随机sleep时间并在它完成睡眠时打印一条消息。代码很简单,所以我不会发布它。当我使用 anExecutorService而不是单独的线程对象时,也会发生同样的事情。

public static void main(String[] args) {
    Thread thread1 = new Thread(new PrintTask("Thread 1"));
    Thread thread2 = new Thread(new PrintTask("Thread 2"));
    Thread thread3 = new Thread(new PrintTask("Thread 3"));

    System.err.println("Starting threads");

    thread1.start();
    thread2.start();
    thread3.start();

    System.err.println("Threads started, main ends\n");
}

输出:

线程 2 为 4907 休眠

线程 1 为 4779 休眠

线程 3 为 537 休眠

线程 3 完成睡眠

线程 1 已完成睡眠

线程 2 完成睡眠

4

4 回答 4

4

我希望它们以与创建和启动相同的顺序显示 (1-2-3)

不,不能保证线程执行的顺序。

于 2013-01-07T17:54:12.543 回答
1

您唯一的保证是(JLS 17.4.5):

线程上的 start() 调用发生在已启动线程中的任何操作之前。

但是不能保证何时涉及多个线程,因此您需要使用某种形式的同步来获得所需的输出。

于 2013-01-07T17:55:17.920 回答
1

我希望它们以与创建和启动相同的顺序显示 (1-2-3)

不提供此类保证。

于 2013-01-07T17:56:29.493 回答
1

线程如何调度运行取决于许多因素,包括任何框架调度程序、操作系统调度程序、硬件等。在没有任何明确协调的情况下,您永远不应依赖并发执行线程之间的特定操作顺序。在启动和实际执行第一条指令之间,调度程序很可能会从 CPU 中取出一个线程。

于 2013-01-07T18:16:58.127 回答