Java Thread.join()詳解

原文地址:http://www.open-open.com/lib/view/open1371741636171.html

點擊閱讀原文

-------------------------------------------------------------

一、使用方式。

join是Thread類的一個方法,啟動線程后直接調用,例如:

Thread t = new AThread(); t.start(); t.join();

二、為什么要用join()方法

在很多情況下,主線程生成并起動了子線程,如果子線程里要進行大量的耗時的運算,主線程往往將于子線程之前結束,但是如果主線程處理完其他的事務后,需要用到子線程的處理結果,也就是主線程需要等待子線程執行完成之后再結束,這個時候就要用到join()方法了。

三、join方法的作用

在JDk的API里對于join()方法是:

join

public final void?join()?throws InterruptedException Waits for this thread to die. Throws: InterruptedException? - if any thread has interrupted the current thread. The?interrupted status?of the current thread is cleared when this exception is thrown.

即join()的作用是:“等待該線程終止”,這里需要理解的就是該線程是指的主線程等待子線程的終止。也就是在子線程調用了join()方法后面的代碼,只有等到子線程結束了才能執行。

四、用實例來理解

寫一個簡單的例子來看一下join()的用法:

1.AThread?類

  1. BThread類

  2. TestDemo?類

    class BThread extends Thread {public BThread() {super("[BThread] Thread");};public void run() {String threadName = Thread.currentThread().getName();System.out.println(threadName + " start.");try {for (int i = 0; i < 5; i++) {System.out.println(threadName + " loop at " + i);Thread.sleep(1000);}System.out.println(threadName + " end.");} catch (Exception e) {System.out.println("Exception from " + threadName + ".run");}}
    }
    class AThread extends Thread {BThread bt;public AThread(BThread bt) {super("[AThread] Thread");this.bt = bt;}public void run() {String threadName = Thread.currentThread().getName();System.out.println(threadName + " start.");try {bt.join();System.out.println(threadName + " end.");} catch (Exception e) {System.out.println("Exception from " + threadName + ".run");}}
    }
    public class TestDemo {public static void main(String[] args) {String threadName = Thread.currentThread().getName();System.out.println(threadName + " start.");BThread bt = new BThread();AThread at = new AThread(bt);try {bt.start();Thread.sleep(2000);at.start();at.join();} catch (Exception e) {System.out.println("Exception from main");}System.out.println(threadName + " end!");}
    }

    打印結果:

    main start.    //主線程起動,因為調用了at.join(),要等到at結束了,此線程才能向下執行。 
    [BThread] Thread start. 
    [BThread] Thread loop at 0 
    [BThread] Thread loop at 1 
    [AThread] Thread start.    //線程at啟動,因為調用bt.join(),等到bt結束了才向下執行。 
    [BThread] Thread loop at 2 
    [BThread] Thread loop at 3 
    [BThread] Thread loop at 4 
    [BThread] Thread end. 
    [AThread] Thread end.    // 線程AThread在bt.join();阻塞處起動,向下繼續執行的結果 
    main end!      //線程AThread結束,此線程在at.join();阻塞處起動,向下繼續執行的結果。
    修改一下代碼:
    public class TestDemo {public static void main(String[] args) {String threadName = Thread.currentThread().getName();System.out.println(threadName + " start.");BThread bt = new BThread();AThread at = new AThread(bt);try {bt.start();Thread.sleep(2000);at.start();//at.join(); //在此處注釋掉對join()的調用} catch (Exception e) {System.out.println("Exception from main");}System.out.println(threadName + " end!");}
    }

    打印結果:

    main start.    // 主線程起動,因為Thread.sleep(2000),主線程沒有馬上結束;[BThread] Thread start.    //線程BThread起動
    [BThread] Thread loop at 0
    [BThread] Thread loop at 1
    main end!   // 在sleep兩秒后主線程結束,AThread執行的bt.join();并不會影響到主線程。
    [AThread] Thread start.    //線程at起動,因為調用了bt.join(),等到bt結束了,此線程才向下執行。
    [BThread] Thread loop at 2
    [BThread] Thread loop at 3
    [BThread] Thread loop at 4
    [BThread] Thread end.    //線程BThread結束了
    [AThread] Thread end.    // 線程AThread在bt.join();阻塞處起動,向下繼續執行的結果

    五、從源碼看join()方法

    在AThread的run方法里,執行了bt.join();,進入看一下它的JDK源碼:

    public final void join() throws InterruptedException {join(0L);
    }
    然后進入join(0L)方法:
    public final synchronized void join(long l)throws InterruptedException
    {long l1 = System.currentTimeMillis();long l2 = 0L;if(l < 0L)throw new IllegalArgumentException("timeout value is negative");if(l == 0L)for(; isAlive(); wait(0L));elsedo{if(!isAlive())break;long l3 = l - l2;if(l3 <= 0L)break;wait(l3);l2 = System.currentTimeMillis() - l1;} while(true);
    }

    單純從代碼上看: * 如果線程被生成了,但還未被起動,isAlive()將返回false,調用它的join()方法是沒有作用的。將直接繼續向下執行。 * 在AThread類中的run方法中,bt.join()是判斷bt的active狀態,如果bt的isActive()方法返回false,在bt.join(),這一點就不用阻塞了,可以繼續向下進行了。從源碼里看,wait方法中有參數,也就是不用喚醒誰,只是不再執行wait,向下繼續執行而已。 * 在join()方法中,對于isAlive()和wait()方法的作用對象是個比較讓人困惑的問題:

    isAlive()方法的簽名是:public final native boolean isAlive(),也就是說isAlive()是判斷當前線程的狀態,也就是bt的狀態。

    wait()方法在jdk文檔中的解釋如下:

    Causes the current thread to wait until another thread invokes the?notify()?method or the?notifyAll()?method for this object. In other words, this method behaves exactly as if it simply performs the call?wait(0).

    The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the?notify?method or the?notifyAll?method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

    在這里,當前線程指的是at。

-------------

更多的Java,Angular,Android,大數據,J2EE,Python,數據庫,Linux,Java架構師,:

http://www.cnblogs.com/zengmiaogen/p/7083694.html


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/538879.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/538879.shtml
英文地址,請注明出處:http://en.pswp.cn/news/538879.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

元類編程--property動態屬性

from datetime import date, datetime class User:def __init__(self, name, birthday):self.name nameself.birthday birthdayself._age 0# def get_age(self):# return datetime.now().year - self.birthday.yearproperty #動態屬性def age(self): #屬性描述符&#x…

php什么情況下使用靜態屬性,oop-做php項目什么時候該使用靜態屬性呢

一般我們做php項目 類里面 定義的方法 或者 屬性 都是普通的 什么時候該用 static 方法和屬性 有什么例子的我很少用 靜態屬性 就有一次用過 我在做會員中心 要獲取 會員菜單的時候 我用的private static $menu array();大家可以討論下嗎回復內容&#xff1a;一般我們做php項目…

vscode運行python文件_vscode怎么運行python文件

1、首先需要確保安裝了VScode的Python插件&#xff0c;打開Python腳本&#xff0c;可以直接拖入&#xff0c;點擊文件&#xff0c;點擊首選項里的用戶設置&#xff0c;這時候會用戶設置配置文件。2、然后在左邊文件CtrlF搜索Python關鍵字&#xff0c;找到pythonPath所在行3、然…

python輸出日期語句_如何從Python的原始語句中提取時間-日期-時間段信息

經過幾天的研究&#xff0c;我想出了以下方法來解決提取問題。在識別命題&#xff0c;然后識別月份并進行提取。在識別“-”&#xff0c;然后識別月份并進行提取。在部分代碼如下所示。(節選&#xff0c;需要上下文中的依賴項)new_w new_s.split()for j in range(len(new_w)):…

datepicker動態初始化

datepicker 初始化動態表單的input&#xff0c;需要調用jquery的on方法來給未來元素初始化。 //對動態添加的時間文本框進行動態初始化$(table).on("focus", ".datepicker", function () {//添加data屬性未來只初始化一次if ($(this).data("datepicke…

oracle中存儲過程 =,oracle中的存儲過程使用

一 存儲過程的基本應用1 創建存儲過程(SQL窗口)create or replace procedure update_staffasbeginupdate staff set name xy;commit;end update_staff;存儲過程適合做更新操作&#xff0c;特別是大量數據的更新2 查看存儲過程在數據字典中的信息(SQL窗口)select object_name,o…

python項目如何上線_django項目部署上線(示例代碼)

前言完善的django項目上線&#xff0c;有很多種上線的方法&#xff0c;比如apache, uwsgi, nginx等。這里只介紹2種&#xff0c;一種是django自帶的&#xff0c;另外一種則是nginx uwsgi完成介紹。這里的系統環境采用的是ubantu系統&#xff0c; python環境采用的是python3, d…

如何檢查python的庫是否安裝成功_如何測試redis是否安裝成功

下載Redis 下載好后 復制所在位置 cd 跳到 D:\Java\64bit 圖中的目錄位置 這樣便啟動成功了。 設置redis密碼的話要 到redis.conf中找到 requirepass關鍵字 設置密碼為123456 redis-cli.exe 進入客戶端 然后 auth 123456 注釋&#xff1a; auth 密碼 set 對象名 [a] 值[123] ge…

第三方類庫的學習心態

我們需要牢牢的記住&#xff1a;所有的第三方庫能實現的功能&#xff0c;我們使用原生的API只要花時間和精力也能實現&#xff0c;但是可能會出現很多的bug而且會花費較多的時間和精力&#xff0c;而且性能也不一定很好&#xff0c;第三方的庫會幫我們封裝底層的一些代碼&#…

HTTP返回碼

響應碼由三位十進制數字組成&#xff0c;它們出現在由HTTP服務器發送的響應的第一行。響應碼分五種類型&#xff0c;由它們的第一位數字表示&#xff1a;1.1xx&#xff1a;信息&#xff0c;請求收到&#xff0c;繼續處理2.2xx&#xff1a;成功&#xff0c;行為被成功地接受、理…

oracle樹結構統計,ORACLE 遞歸樹型結構統計匯總

區域平臺統計報表&#xff0c;省--市--區 匯總&#xff0c;還有各級醫院&#xff0c;匯總與列表要在一個列表顯示。用到ORACLE 會話時臨時表 GLOBAL TEMPORARY TABLE ON COMMIT PRESERVE ROWS;遞歸樹&#xff1a; START WITH P.PARENTORG ‘ROOT‘CONNECT BY PRIOR P.ORG…

我們真的需要使用RxJava+Retrofit嗎?

原文&#xff1a;http://blog.csdn.net/TOYOTA11/article/details/53454925 點擊閱讀原文 RxJava詳解&#xff1a;http://gank.io/post/560e15be2dca930e00da1083 Retrofit詳解&#xff1a;http://www.tuicool.com/articles/AveimyQ --------------------------------------…

python ide如何運行_ide - 如何運行Python程序?

你問我很高興&#xff01; 我正在努力在我們的wikibook中解釋這個問題&#xff08;這顯然是不完整的&#xff09;。 我們正在與Python新手合作&#xff0c;并且必須通過您正在詢問的內容幫助我們&#xff01; Windows中的命令行Python&#xff1a; 使用編輯器中的“保存”或“另…

邏輯回歸算法_算法邏輯回歸

logistic回歸又稱logistic回歸分析&#xff0c;是一種廣義的線性回歸分析模型&#xff0c;常用于數據挖掘&#xff0c;疾病自動診斷&#xff0c;經濟預測等領域。例如&#xff0c;探討引發疾病的危險因素&#xff0c;并根據危險因素預測疾病發生的概率等。以胃癌病情分析為例&a…

使用docker搭建wordpress網站

概述 使用docker的好處就是盡量減少了環境部署&#xff0c;可靠性強&#xff0c;容易維護&#xff0c;我使用docker搭建wordpress的主要目標有下面幾個首先我重新生成數據庫容器可以保證數據庫數據不丟失&#xff0c;重新生成wordpress容器保證wordpress網站數據不丟失&#xf…

XUtils之注解機制詳解

原文&#xff1a;http://blog.csdn.net/rain_butterfly/article/details/37931031 點擊閱讀原文 ------------------------------------------------------ 這篇文章說一下xUtils里面的注解原理。 先來看一下xUtils里面demo的代碼&#xff1a; [java] view plaincopy print?…

oracle ko16mswin949,mysql字符集 - osc_wq7ij8li的個人空間 - OSCHINA - 中文開源技術交流社區...

恰當的字符集&#xff0c;暢快的體驗&#xff01;00、Oracle字符集Subsets and Supersets #子集與超集Table A-11 Subset-Superset PairsSubset(子集)Superset(超集)AR8ADOS710AR8ADOS710TAR8ADOS720AR8ADOS720TAR8ADOS720TAR8ADOS720AR8APTEC715AR8APTEC715TAR8ARABICMACTAR…

曼徹斯特編碼_兩種編碼方式以及兩種幀結構

一、不歸零制編碼(Non-Return to Zero)對于不歸零制編碼是最簡單的一種編碼方式&#xff0c;正電平代表1&#xff0c;負電平代表0。如下圖&#xff1a;其實在不歸零制編碼中有一個很明顯的缺陷&#xff0c;那就是它不是自同步碼。對于上圖&#xff0c;你知道它傳輸的數據是什么…

python用一行代碼編寫一個回聲程序_使用Python的多回聲測驗

我在寫一個程序來管理一個五問多的問題- 關于全球變暖的選擇測驗和計算數字 正確答案。 我首先創建了一本字典&#xff0c;比如&#xff1a;questions \ { "What is the global warming controversy about?": { "A": "the public debate over wheth…