在面試中常常會遇到這樣的問題:在主線程中有兩個子線程,若是能讓着兩個子線程能順序的執行?
答案天然是用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方法裏面能傳遞時間參數,大概做用就是等待指定時間以後,若是以前線程還未執行完成,那麼久再也不等待。線程