因爲前段時間比較忙,線程這快學習停滯了,只能利用週日的時間來寫寫博客了,
多線程Join方法
的做用就是把指定的線程加入到當前線程,讓主線程
等待子線程
結束以後才能繼續運行,從而完成同步操做java
<!-- more -->git
join()
的做用:讓主線程
等待子線程
結束以後才能繼續運行,首先先來看下以採集
爲案例的代碼,統計採集所消耗的時長微信
需求:當全部線程任務執行完畢,統計最終消耗時長多線程
public class ThreadJoin { public static void main(String[] args) throws InterruptedException { long startTime = System.currentTimeMillis(); Thread t1 = new Thread(new CaptureRunnable("M1", 5_000L)); Thread t2 = new Thread(new CaptureRunnable("M2", 3_000L)); Thread t3 = new Thread(new CaptureRunnable("M3", 2_000L)); t1.start(); t2.start(); t3.start(); System.out.println("採集完成,消耗 " + (System.currentTimeMillis() - startTime)); } } class CaptureRunnable implements Runnable { private String machineName;//採集任務名 private Long spendTime;//採集工做消耗時長 public CaptureRunnable(String machineName, Long spendTime) { this.machineName = machineName; this.spendTime = spendTime; } @Override public void run() { try { System.out.println(machineName + "開始採集"); Thread.sleep(spendTime); } catch (InterruptedException e) { e.printStackTrace(); } } }
在ThreadJoin
的代碼中,咱們建立了主線程main
,和實現了Runnable
的CaptureRunnable
子線程,運行main
方法,能夠看到在未使用join()
的狀況下,統計結果並不理想,正確輸出應該是5000毫秒以上
ide
採集完成,消耗 1 M1開始採集 M2開始採集 M3開始採集
在start
方法下添加join
操做,運行main
方法,發現無論那個線程先執行,結果都是5000毫秒以上
,由於主線程main
接收到了M1,M2,M3
三個線程的join
指令,這個時候主線程
則會處於阻塞狀態,直到子線程
執行完畢後纔會繼續執行下去...源碼分析
t1.start(); t2.start(); t3.start(); t1.join(); t2.join(); t3.join();
M2開始採集 M1開始採集 M3開始採集 採集完成,消耗 5001
去掉M1
線程調用的join
,而後運行main
方法,從日誌輸出中能夠發現,main
會等待M2,M3
執行完畢後纔會繼續執行下去學習
M1開始採集 M3開始採集 M2開始採集 採集完成,消耗 3001
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; } } }
說明this
從代碼中,咱們能夠發現。當millis==0
時,會進入while(isAlive())
循環,系統會判斷主線程
是否處於活躍狀態,若是處於活躍狀態,主線程
就會不停的等待。spa
問題.net
爲何子線程
調用join()
阻塞的倒是主線程呢?join()
方法中的isAlive()
應該是判斷子線程
是否處於活躍的狀態,對應的wait(0)
也應該是讓子線程
等待纔對
答案
首先從源碼中咱們能夠發現它是被synchronized
修飾的方法,當前線程的對象調用join
後,其實獲取到了子線程M1,M2,M3
的鎖,當子線程鎖釋放後纔會繼續執行主線程
的操做
使用jvisualvm
分析器,能夠發現Thread-1-3
與主線程main
,處於等待的是主線程
,子線程由於調用了sleep
處於休眠狀態(爲了演示耗時操做)
微信公衆號:battcn
(歡迎調戲)