Java中新创建的线程执行顺序是什么?

5
class Test {
    boolean isFirstThread = true;

    private synchronized void printer(int threadNo) {
        if(isFirstThread) {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isFirstThread = false;
        System.out.println(threadNo);
   }

   public void starter() {
        new Thread(){
            @Override()
            public void run() {
                printer(0);
            }
        }.start();

        new Thread(){
            @Override()
            public void run() {
                printer(1);
            }
        }.start();

        new Thread(){
            @Override()
            public void run() {
                printer(2);
            }
        }.start();

        new Thread(){
            @Override()
            public void run() {
                printer(3);
            }
        }.start();
    }
}

在上面的代码中,当我从主函数调用starter时,我创建了四个新线程来调用一个同步函数。我知道线程的执行顺序是无法预测的,除非它们等待一段时间,以便第一个线程可以完成并退出同步块。在这种情况下,我希望所有线程都被保持在队列中,因此我期望答案是
0
1
2
3
但是一致地(我运行程序超过20次)我得到的输出为
0
3
2
1
这意味着线程被保存在堆栈而不是队列中。为什么会这样?谷歌搜索结果中的每个答案都说它是一个队列,但是我却得到了一个堆栈。我想知道将线程保存在堆栈中(这是相反直觉的)而不是队列的原因是什么?

3
除非您提供适当的同步,否则线程始终会异步运行,没有明确定义的顺序。 - markspace
这取决于操作系统如何实现互斥锁,注意如果您更改了代码,例如等待时间缩短了很多,您可能会得到不同的结果。尝试使用2毫秒而不是2000。 - Peter Lawrey
http://www.catb.org/jargon/html/N/nasal-demons.html - Louis Wasserman
1个回答

10

线程启动的顺序取决于操作系统,Java语言规范中未指定。您在主线程中调用start方法,但是新线程分配和开始处理其Runnable或run方法的时间由操作系统的调度程序决定。

请注意,不要依赖线程启动的顺序。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接