先说结论:
Join可以把指定的线程加入到当前线程,为顺将两个交替执行的线程合并为顺序执行的线程。比如在线程A中调用了线程B的Join()方法,直到线程B执行完毕后,才会继续执行线程A。
底层实现是基于对象的wait和notify方法来实现的。当一个线程A执行另一个线程B的join()方法时,因为join方法是synchronized关键字修饰的,所以线程A会拿到线程B的对象锁,然后在底层会执行线程B的wait方法,那么线程A就会释放锁并进入线程B的等待池中,当线程B执行完毕后,JVM底层会自动调用线程B对象的notifyAll()方法来通知所有等待该对象锁上的线程,包括线程A。这个时候线程A会重新进入就绪状态,等待获取CPU资源继续向下执行。
图上的代码解析:首先创建了两个线程对象,分别是:testA1跟testA2,然后在主线程中调用了testA1的join方法,那么主线程会获取到testA1的对象锁,然后在底层会调用testA1的wait方法,这个时候主线程就会释放掉testA1的对象锁,那么就会进入阻塞状态并进入testA1的等待池,那么就没有办法执行testA2.start方法,然后就只能等待testA1线程执行完毕,testA1线程执行完毕后,会在jvm虚拟机中,调用testA1对象的notifyall方法,用来唤醒所有等待这个对象锁的线程,这个时候主线程就会被唤醒,然后执行testA2.start方法
1.示例代码:
public class test { public static void main(String[] args) throws InterruptedException { testA testA1 = new testA(); testA testA2 = new testA(); testA1.start(); testA2.start(); } static class testA extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("名称为:" + Thread.currentThread().getName() + "的线程:" + i); } } } }
运行结果:
可以看到线程是同步执行的,但如果想要等待A1线程执行完成再执行A2线程,可以使用线程的join方法
2.加join方法示例代码:
public class test { public static void main(String[] args) throws InterruptedException { testA testA1 = new testA(); testA testA2 = new testA(); testA1.start(); // 在main方法中执行 testA1.join(); 所以当前线程是 主线程 testA1.join(); testA2.start(); } static class testA extends Thread{ @Override public void run() { for (int i = 0; i < 100; i++) { System.out.println("名称为:" + Thread.currentThread().getName() + "的线程:" + i); } } } }
运行结果: