摘要:當時,會進入循環,系統會判斷主線程是否處于活躍狀態,如果處于活躍狀態,主線程就會不停的等待。
介紹由于前段時間比較忙,線程這快學習停滯了,只能利用周日的時間來寫寫博客了,多線程Join方法的作用就是把指定的線程加入到當前線程,讓主線程等待子線程結束之后才能繼續運行,從而完成同步操作
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毫秒以上
采集完成,消耗 1 M1開始采集 M2開始采集 M3開始采集使用join
在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部分join
去掉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; } } }
說明
從代碼中,我們可以發現。當millis==0時,會進入while(isAlive())循環,系統會判斷主線程是否處于活躍狀態,如果處于活躍狀態,主線程就會不停的等待。
問題
為什么子線程調用join()阻塞的卻是主線程呢?join()方法中的isAlive()應該是判斷子線程是否處于活躍的狀態,對應的wait(0)也應該是讓子線程等待才對
答案
首先從源碼中我們可以發現它是被synchronized修飾的方法,當前線程的對象調用join后,其實獲取到了子線程M1,M2,M3的鎖,當子線程鎖釋放后才會繼續執行主線程的操作
使用jvisualvm分析器,可以發現Thread-1-3與主線程main,處于等待的是主線程,子線程因為調用了sleep處于休眠狀態(為了演示耗時操作)
- 說點什么全文代碼:https://git.oschina.net/battcn/battcn-concurent/tree/master/Chapter1-1/battcn-thread/src/main/java/com/battcn/chapter3
個人QQ:1837307557
battcn開源群(適合新手):391619659
微信公眾號:battcn(歡迎調戲)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/67631.html
摘要:文本將介紹兩種可以優雅的終止線程的方式第一種在多線程模式中有一種叫兩步終止的模式可以優雅的終止線程,這種模式采用了兩個步驟來終止線程,所以叫兩步終止模式。 Java中原來在Thread中提供了stop()方法來終止線程,但這個方法是不安全的,所以一般不建議使用。文本將介紹兩種可以優雅的終止線程的方式... 第一種 在JAVA《Java多線程模式》中有一種叫Two-Phase Term...
摘要:在之前,不能為線程單獨設置或指定一個默認的,為了設置,需要繼承并覆寫方法。幸運的是后線程提供了一個方法,用來捕獲并處理因線程中拋出的未知異常,以避免程序終止。 在單線程的開發過程中,通常采用try-catch的方式進行異常捕獲,但是這種方式在多線程環境中會顯得無能為力,而且還有可能導致一些問題的出現,比如發生異常的時候不能及時回收系統資源,或者無法及時關閉當前的連接... 概述 Ja...
摘要:定義等待該線程終止,比如線程調用了線程的,那么線程要等到線程執行完后,才可以繼續執行。 定義 等待該線程終止,比如A線程調用了B線程的join,那么A線程要等到B線程執行完后,才可以繼續執行。 示例 public class JoinDemo { static class JoinThread1 implements Runnable { Thread thre...
摘要:思想把大任務分割成多個小任務,再把小任務的結果匯總,最終得到大任務的結果。當一個線程執行完當前隊列的任務時,他就會去竊取其他隊列的任務來執行。當雙端隊列只有一個任務時,線程之間會競爭。 思想 把大任務分割成多個小任務,再把小任務的結果匯總,最終得到大任務的結果。 步驟如下: 任務分割 結果匯總 示例圖 showImg(https://segmentfault.com/img/bVb...
摘要:上一章介紹過關鍵字,使用它可以給程序互斥部分加上一把鎖從而達到同步的效果,但錯誤的用法會導致多個線程同時被阻塞死鎖死鎖多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。由于線程被無限期地阻塞,因此程序不可能正常終止。 上一章介紹過synchronized關鍵字,使用它可以給程序互斥部分加上一把鎖從而達到同步的效果,但錯誤的用法會導致多個線程同時被阻塞.... 死鎖 死鎖...
閱讀 1675·2021-11-15 11:37
閱讀 3408·2021-09-28 09:44
閱讀 1649·2021-09-07 10:15
閱讀 2784·2021-09-03 10:39
閱讀 2687·2019-08-29 13:20
閱讀 1291·2019-08-29 12:51
閱讀 2204·2019-08-26 13:44
閱讀 2125·2019-08-23 18:02