在面试中经常会遇到这样的问题:在主线程中有两个子线程,如果能让着两个子线程能顺序的执行?
答案自然是用join来使得两个线程顺序执行,先看一下具体代码

public class ThreadOfJoin {    public static void main(String[] args) throws Exception {        MyThread luck = new MyThread("Luck");        MyThread timi = new MyThread("Timi");        luck.start();        luck.join();        timi.start();    }    @Data    static class MyThread extends Thread {        private String userName;        public MyThread(String userName) {            this.userName = userName;        }        @Override        public void run() {            try {                for (int i = 0; i < 5; i++) {                    System.out.println(userName + " - " + i);                    Thread.sleep(1000);                }            } catch (Exception e) {                e.printStackTrace();            }        }    }}

每个线程启动后,打印五次信息,通过不同的名字来区分是哪个线程打印的。执行结果如下

Luck - 0Luck - 1Luck - 2Luck - 3Luck - 4Timi - 0Timi - 1Timi - 2Timi - 3Timi - 4

通过结果可以看到join可以使得两个线程是顺序执行,那为什么join能控制线程顺序执行呢,我们看下join的具体实现

//外部调用的方法public final void join() throws InterruptedException {    join(0);}//内部的具体实现public final synchronized void join(long millis) throws InterruptedException {    long base = System.currentTimeMillis();    long now = 0;    if (millis < 0) {        throw new IllegalArgumentException("timeout value is negative");    }    if (millis == 0) {        while (isAlive()) {            wait(0);        }    } else {        while (isAlive()) {            long delay = millis - now;            if (delay <= 0) {                break;            }            wait(delay);            now = System.currentTimeMillis() - base;        }    }}

首先join通过synchronized关键字来保证线程安全,主线程在调用了luck.start()之后调用了luck.join(),当luck线程未执行完成是,主线程会被以下代码阻塞

if (millis == 0) {//join()方法默认milis为0    while (isAlive()) {//线程未执行完成,此条件为true        wait(0);//等待notify    }}

当luck线程执行完成之后,此线程的生命周期即将结束,在生命周期结束前,luck线程会使用notifyAll()方法,通知所有正在等待该对象锁的线程(我即将死去,你们不要再等了)。wait(0)接收到notify之后,会再次进行isAlive()判断,luck死亡之后,就跳出循环,join方法结束,之后就继续执行主线程中的其他代码。

同时我们也能看到join方法里面能传递时间参数,大概作用就是等待指定时间之后,如果之前线程还未执行完成,那么久不再等待。