日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java join()源码_Java Thread的join() 之刨根问底

發布時間:2025/4/16 java 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java join()源码_Java Thread的join() 之刨根问底 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

0.Join()

線程的合并的含義就是 將幾個并行線程的線程合并為一個單線程執行,應用場景是 當一個線程必須等待另一個線程執行完畢才能執行時,Thread類提供了join方法來完成這個功能,注意,它不是靜態方法。

join有3個重載的方法:

void join():當前線程等該加入該線程后面,等待該線程終止。

void join(long millis):當前線程等待該線程終止的時間最長為 millis 毫秒。 如果在millis時間內,該線程沒有執行完,那么當前線程進入就緒狀態,重新等待cpu調度。

void join(long millis,int nanos):等待該線程終止的時間最長為 millis 毫秒 + nanos納秒。如果在millis時間內,該線程沒有執行完,那么當前線程進入就緒狀態,重新等待cpu調度。

1.使用方法

新建一個Thread類,重寫run()方法:

public class MyThread extends Thread {

@Override

public void run() {

System.out.println("子線程執行完畢");

}

}

復制代碼

新建測試類,測試Join()方法:

public class TestThread {

public static void main(String[] args) {

//循環五次

for (int i = 0; i < 5; i++) {

MyThread thread = new MyThread();

//啟動線程

thread.start();

try {

//調用join()方法

thread.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("主線程執行完畢");

System.out.println("~~~~~~~~~~~~~~~");

}

}

}

復制代碼

輸出結果如下:

子線程執行完畢

主線程執行完畢

~~~~~~~~~~~~~~~

子線程執行完畢

主線程執行完畢

~~~~~~~~~~~~~~~

子線程執行完畢

主線程執行完畢

~~~~~~~~~~~~~~~

子線程執行完畢

主線程執行完畢

~~~~~~~~~~~~~~~

子線程執行完畢

主線程執行完畢

~~~~~~~~~~~~~~~

復制代碼

結果分析: 子線程每次都在主線程之前執行完畢,即子線程會在主線程之前執行。

代碼中循環5次是為了排除線程執行的隨機性,若不能說明問題,可以調大循環次數進行測試。

2.原理分析

查看Thread類源碼:

public final void join() throws InterruptedException {

//當調用join()時,實際是調用join(long)方法

join(0);

}

復制代碼

查看Join(long)方法源碼:

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) { //由于上一步傳入參數為0,因此調用當前判斷

while (isAlive()) { //判斷子線程是否存活

wait(0); //調用wait(0)方法

}

} else {

while (isAlive()) {

long delay = millis - now;

if (delay <= 0) {

break;

}

wait(delay);

now = System.currentTimeMillis() - base;

}

}

}

復制代碼

查看isAlive()方法源碼:

/**

* Tests if this thread is alive. A thread is alive if it has

* been started and has not yet died.

* 測試線程是否還活著。如果線程存活的話它就是已經開始,還沒有死亡的狀態。

* @return true if this thread is alive;

* false otherwise.

*/****

public final native boolean isAlive();

復制代碼

說明: 該方法為本地方法,判斷線程對象是否存活,若線程對象調用了start()方法,在沒有死亡的情況下此判斷為true。在上述例子中,由于調用了子線程的start()方法,并且沒有結束操作,因此判斷true。

查看wait()方法源碼:

public final native void wait(long timeout) throws InterruptedException;

復制代碼

說明: 該方法為本地方法,調用此方法的當前線程需要釋放鎖,并等待喚醒。在上述例子中,主線程調用子線程對象的join()方法,因此主線程在此位置需要釋放鎖,并進行等待。

wait()與wait(0)的區別:

查看wait()方法源碼,wait()方法只調用了wait(0),如下:

public final void wait() throws InterruptedException {

wait(0);

}

因此,wait()與wait(0)相同。

復制代碼

我們來擼一擼上述步驟: 主線程wait()等待,子線程調用了run()執行,打印“子線程執行完畢”。此時,主線程還沒被喚醒,還沒有執行下面的操作。那么,問題來了,誰?在什么時候?喚醒了主線程呢?

查看Thread類中存在exit()方法,源碼如下:

/**

* This method is called by the system to give a Thread

* a chance to clean up before it actually exits.

* 這個方法由系統調用,當該線程完全退出前給它一個機會去釋放空間。

*/

private void exit() {

if (group != null) { //線程組在Thread初始化時創建,存有創建的子線程

group.threadTerminated(this); //調用threadTerminated()方法

group = null;

}

/* Aggressively null out all reference fields: see bug 4006245 */

target = null;

/* Speed the release of some of these resources */

threadLocals = null;

inheritableThreadLocals = null;

inheritedAccessControlContext = null;

blocker = null;

uncaughtExceptionHandler = null;

}

復制代碼

通過debug,exit()在線程執行完run()方法之后會被調用,此時線程組中存在當前子線程,因此會調用線程組的threadTerminated()方法。

查看ThreadGroup.threadTerminated()方法源碼:

/** Notifies the group that the thread {@code t} has terminated.

* 通知線程組,t線程已經終止。

*

void threadTerminated(Thread t) {

synchronized (this) {

remove(t); //從線程組中刪除此線程

if (nthreads == 0) { //當線程組中線程數為0時

notifyAll(); //喚醒所有待定中的線程

}

if (daemon && (nthreads == 0) &&

(nUnstartedThreads == 0) && (ngroups == 0))

{

destroy();

}

}

}

復制代碼

通過此方法,將子線程從線程組中刪除,并喚醒其他等待的線程。在上述例子中,此時子線程被銷毀,并釋放占用的資源,并喚醒等待中的線程。而在join()方法中等待的主線程被喚醒,并獲得鎖,打印“主線程執行完畢”。

3.總結

Join()方法,使調用此方法的線程wait()(在例子中是main線程),直到調用此方法的線程對象(在例子中是MyThread對象)所在的線程(在例子中是子線程)執行完畢后被喚醒。

由于線程的啟動與銷毀其實是由操作系統進行操作,所以在描述的時候刻意略去,如果有疑惑的地方,可以查看C++編寫的本地方法。

復制代碼

總結

以上是生活随笔為你收集整理的java join()源码_Java Thread的join() 之刨根问底的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 东京干手机福利视频 | 韩国中文字幕在线观看 | 久久免费手机视频 | 奇米视频在线 | 久久精品亚洲a | 成人蜜桃视频 | 国产一区二区三区日韩 | www.五月天com | 久久乐视频 | 成人精品一区二区三区电影黑人 | 欧美精品一区二区三区视频 | 欧美拍拍视频 | 麻豆传媒一区二区三区 | 操操操日日日 | 国产精品乱码一区二区三区 | 一级黄色片在线免费观看 | 香蕉大久久 | 最新99热 | 国产第一页av | 久久二 | 国产真人做爰毛片视频直播 | 黄色h视频 | 国产精品久久久久不卡 | 可以看黄色的网站 | 亚洲精品国产精品乱码不99按摩 | 中文字幕在线欧美 | 亚洲免费视频大全 | 精品久久久久久久中文字幕 | 亚洲永久免费 | 国产尻逼视频 | 日本a∨视频 | 欧美性生活一区二区 | 久草资源在线视频 | 国产中文在线视频 | 男人和女人做爽爽视频 | 亚洲精品国产精品国自产观看 | 精品国产成人亚洲午夜福利 | 国产午夜在线 | 91亚洲精品久久久蜜桃网站 | 欧美日韩1 | 亚洲精品视频一二三区 | 中文亚洲av片不卡在线观看 | 亚欧乱色| 色妞网站 | 国产精品入口66mio男同 | 精品国产欧美一区二区三区成人 | 日韩精品电影在线 | 国产精品无码AV | 久久久精品人妻一区二区三区 | 国产视频成人 | 亚洲男人天堂2022 | 在线草| 337p亚洲欧洲色噜噜噜 | 国内自拍偷拍网 | 日韩av色| 看片日韩 | 污污网站在线看 | 日韩夜夜高潮夜夜爽无码 | 久久视 | 三级免费看| 香蕉av777xxx色综合一区 | 91插插插视频 | 少妇xxxxxx| 呦女精品| 欧美成人a | 五月开心激情 | 久久伊人草 | 中文字幕手机在线视频 | av香蕉| 欧美日韩国产一区二区在线观看 | 日本韩国欧美中文字幕 | 国产黄色片网站 | 熟妇高潮喷沈阳45熟妇高潮喷 | 成人亚洲精品 | www中文字幕在线观看 | 国产小视频网址 | 韩国视频一区二区三区 | 欧美精品第1页 | 68日本xxxxxⅹxxx59| 在线国产日韩 | たちの熟人妻av一区二区 | 中文字幕在线视频免费 | 成年人的天堂 | 日韩精品一区二区三区在线视频 | 日韩在线观看av | 人人爽久久涩噜噜噜网站 | 成人颜色网站 | 国产偷人 | 免费看av的网址 | 国产精久久一区二区三区 | 成人午夜网址 | 在线看片亚洲 | 无码少妇一区二区 | 这里只有精品视频 | 久久久久一区 | 成人午夜免费电影 | 在线国产日韩 | 五月天丁香网 | 久久久精品中文字幕麻豆发布 |