源碼分析:
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方法中,當前執行線程會循環校驗被調用線程對象的isAlive方法來確認被調用線程是否執行完任務,如果沒有,則會調用使線程阻塞的wait方法。
分析wait方法源碼:wait方法是被native修飾的,說明直接使用其他語言與操作系統交互,停止當前線程,也就是當前正在調用join方法執行的線程。
如果代碼如圖:
主線程是執行線程,將被阻塞。
在測試下:
public void testNotify() throws InterruptedException{ // 創建任務隊列 List<ThreadTask> taskList = new ArrayList<>(); ThreadTask task = new ThreadTask(-1); Thread t1 = new Thread(task); Thread t2 = new Thread(new Runnable() { @Override public void run() { Thread t2 = Thread.currentThread(); try { System.out.println("當前線程" + t2.getName()); t2.join();// 主線程調用線程t的join方法,被阻塞的是主線程 } catch (InterruptedException e) { } System.out.println("當前線程" + t2.getName() + "任務結束"); } }); t1.start(); t1.join(); System.out.println("T1結束"); t2.start(); t2.join(); System.out.println("主線程"); task.notifyAll(); }
執行結果:
程序進入了鎖死狀態。t2線程中執行了t2.join使得t2線程進入阻塞狀態,也就是t2線程永遠不肯能結束,而在主線程又調用了t2.join,主線程也鎖死。