在面试中常常会遇到这样的问题:在主线程中有两个子线程,若是能让着两个子线程能顺序的执行?
答案天然是用join来使得两个线程顺序执行,先看一下具体代码java
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 - 0 Luck - 1 Luck - 2 Luck - 3 Luck - 4 Timi - 0 Timi - 1 Timi - 2 Timi - 3 Timi - 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线程未执行完成是,主线程会被如下代码阻塞ide
if (millis == 0) {//join()方法默认milis为0 while (isAlive()) {//线程未执行完成,此条件为true wait(0);//等待notify } }
当luck线程执行完成以后,此线程的生命周期即将结束,在生命周期结束前,luck线程会使用notifyAll()方法,通知全部正在等待该对象锁的线程(我即将死去,大家不要再等了)。wait(0)接收到notify以后,会再次进行isAlive()判断,luck死亡以后,就跳出循环,join方法结束,以后就继续执行主线程中的其余代码。this
同时咱们也能看到join方法里面能传递时间参数,大概做用就是等待指定时间以后,若是以前线程还未执行完成,那么久再也不等待。线程