【问题标题】:Multiple threads running in the fixed order based on the compile order [duplicate]基于编译顺序以固定顺序运行的多个线程[重复]
【发布时间】:2020-11-23 06:58:43
【问题描述】:

我正在尝试使用下面的代码找出多线程的顺序。
当一个线程在同步部分运行时,我使用同步来阻塞其他线程。我原以为线程 1 应该首先开始和结束,然后是线程 2,最后是 3。但结果总是显示 1,3,2

那么为什么会这样呢?不应该像 1 2 3 或 1 3 2 那样随机执行吗?

public class hello {
    static class runnablethread extends Thread{
        private static int k = 5;
        public void run() {
            synchronized (runnablethread.class) {
                System.out.println(Thread.currentThread().getName() + " start:" + System.currentTimeMillis());
                try {
                    Thread.sleep(1000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + " end:" + System.currentTimeMillis());
        }
    }
    public static void main(String[] args) {
        runnablethread r1 = new runnablethread();
        new Thread(r1,"Thread1").start();
        new Thread(r1,"Thread2").start();
        new Thread(r1,"Thread3").start();
    }
}
Thread1 start:1606114065880

Thread1 end:1606114066885

Thread3 start:1606114066885

Thread3 end:1606114067889

Thread2 start:1606114067889

Thread2 end:1606114068894

【问题讨论】:

标签: java multithreading synchronization thread-safety


【解决方案1】:

Thread.start() 方法实际上并没有调用您的 run 方法,它只是表明您的线程已准备好被调度执行。 JVM然后调度线程的执行,但是这个调度并不能保证调度的顺序和它们启动的顺序是一样的。

在您的具体情况下,代码序列

new Thread(r1,"Thread1").start();
new Thread(r1,"Thread2").start();
new Thread(r1,"Thread3").start();

快速执行,JVM 最终有 3 个线程准备好调度。

如果你想等待某个线程的终止,你可以使用join方法。

也可以使用 setPriority() 方法改变线程的优先级。

如果代码被多次执行,我们可以注意到线程是随机启动的

$ java hello
Thread1 start:1606124964911
Thread1 end:1606124965915
Thread3 start:1606124965915
Thread3 end:1606124966921
Thread2 start:1606124966921
Thread2 end:1606124967926

$ java hello
Thread1 start:1606124969152
Thread1 end:1606124970155
Thread3 start:1606124970155
Thread2 start:1606124971157
Thread3 end:1606124971157
Thread2 end:1606124972162

$ java hello
Thread1 start:1606124975920
Thread1 end:1606124976925
Thread3 start:1606124976925
Thread3 end:1606124977926
Thread2 start:1606124977926
Thread2 end:1606124978930

$ java hello
Thread2 start:1606124980589
Thread3 start:1606124981592
Thread2 end:1606124981592
Thread3 end:1606124982594
Thread1 start:1606124982594
Thread1 end:1606124983599

【讨论】:

  • 其实我知道 start() 方法只是为了时间表。但是当您在线程 3 之后添加线程 4 时,执行顺序将始终为 1、4、3、2,这意味着在执行线程 1 之后顺序是相反的(从底部的句子开始?)?不应该像 1 4 2 3 或 1 2 4 3 那样随机执行吗?
  • 我尝试了很多次,但总是 1 4 3 2。我很惊讶你的最后结果显示线程 2 先启动,这证实线程是随机启动的。我不确定为什么我的结果总是一样的,也许是因为软件(不确定)?我使用 intelljj。
  • 它可能取决于操作系统、当前 jvm 版本、处理器和内核的数量。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多