【问题标题】:Threads get scrambled during execution线程在执行期间被打乱
【发布时间】:2013-01-08 02:16:58
【问题描述】:

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

这是为什么?

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

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 完成睡眠

【问题讨论】:

  • 你认为它们为什么会按顺序出现?无法保证线程被赋予时间片的顺序
  • 线程的全部目的是执行独立的任务。如果您希望以特定顺序执行任务,您将使用循环,而不是创建线程。

标签: java multithreading threadpool


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      不提供此类保证。

      【讨论】:

        【解决方案4】:

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

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

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

        【讨论】:

        • 我曾尝试使用ExecutorService 使用execute() 方法,但这并没有什么不同。我也用submit() 尝试过,但这也没有什么不同。
        猜你喜欢
        • 2018-09-11
        • 1970-01-01
        • 2012-01-30
        • 2017-08-27
        • 2021-07-25
        • 1970-01-01
        • 1970-01-01
        • 2018-05-08
        • 1970-01-01
        相关资源
        最近更新 更多