我想通过join让线程 a b c d顺序打印,但是现在是乱序打印
public class ExJoin extends Thread {
Thread thread;
public ExJoin(){
}
public ExJoin(Thread thread){
this.thread = thread;
}
@Override
public void run() {
try {
if (thread != null){
thread.join();
}
System.out.println(Thread.currentThread().getName()+" is running");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Thread threadA = new ExJoin();
threadA.setName("A");
Thread threadB = new ExJoin(threadA);
threadB.setName("B");
Thread threadC = new ExJoin(threadB);
threadC.setName("C");
Thread threadD = new ExJoin(threadC);
threadD.setName("D");
threadC.start();
threadD.start();
threadA.start();
threadB.start();
}
}
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
在run方法里加个sleep试试。
按照楼主的代码逻辑,
join是无法做到有序的,因为A/B/C/D线程的启动运行依赖于CPU调度,如果线程B未启动线程C调用threadB.join方法是不会生效的。可以看看jdk内置的逻辑实现isAlive()为false时直接返回了。在
run方法中sleep(1000)确实会顺序出现。我猜测可能是指令重排序,前面的线程已经就绪,但是后面的线程对象还没有创建出来,所以出现了乱序。我们来看看

join方法的具体实现:无参的
join方法即执行下列代码:然后我们看看

isAlive方法的实现,发现isAlive是一个 native 方法 —— 不过没关系,我们可以看它的 javadoc 注释:"A thread is alive if it has been started and has not yet died"
—— 所以一个线程只有在线程已经开始之后(并且还没有结束),
isAlive方法才会返回true。也就是说只有线程是 started (已经启动)之后,
join方法才会生效(即阻塞直到线程执行完毕)。首先,每个线程新建完毕时候(就是 new Thread(...)) 调用之后,此时线程处于 NEW 状态;
然后线程的
start方法调用之后,此时线程才处于可运行状态(RUNNABLE,即 started)。但是所有线程在何时运行,都是由 JVM 来调度的。
代码:
这四个方法都是处于主线程中,
threadC.start()之后,JVM 新建了线程 threadC,那么如果这时候 JVM 调度 threadC 来运行,而不是继续运行主线程,那么 threadC 中去调用threadB.join()便会直接返回而不是等待 threadB 完成 —— 因为此时 threadB 的 start 方法还没有被调用, threadB 并没有处于运行状态(started)。如果要实现顺序输出的逻辑,可以这样修改代码:
某次的运行结果:

我们使用join()方法是为了实现线程同步,那么是事先知道事务的处理先后顺序,然后用join()方法来保证这个先后顺序。你现在的代码设计上就存在一定的逻辑问题,虽然执行上没有报错,但是纯粹属于实验测试,没有任何实际场景需要。另外还缺少对比测试,无法体现join()方法的作用。
首先,关于join()方法作用的理解,建议你看一下这篇文章《线程中join方法的作用》
然后,关于你的代码,我进行一些调整,现粘贴如下:
运行结果对比: