Java中的Thread.join()詳解
一、使用方式。
join是Thread類的一個(gè)方法,啟動(dòng)線程后直接調(diào)用,例如:
Thread t = new AThread(); t.start(); t.join();
二、為什么要用join()方法
在很多情況下,主線程生成并起動(dòng)了子線程,如果子線程里要進(jìn)行大量的耗時(shí)的運(yùn)算,主線程往往將于子線程之前結(jié)束,但是如果主線程處理完其他的事務(wù)后,需要用到子線程的處理結(jié)果,也就是主線程需要等待子線程執(zhí)行完成之后再結(jié)束,這個(gè)時(shí)候就要用到j(luò)oin()方法了。
三、join方法的作用
在JDk的API里對(duì)于join()方法是:
即join()的作用是:“等待該線程終止”,這里需要理解的就是該線程是指的主線程等待子線程的終止。也就是在子線程調(diào)用了join()方法后面的代碼,只有等到子線程結(jié)束了才能執(zhí)行。
四、用實(shí)例來理解
寫一個(gè)簡單的例子來看一下join()的用法:
1.AThread 類
BThread類
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!");
}
}打印結(jié)果:
main start. //主線程起動(dòng),因?yàn)檎{(diào)用了at.join(),要等到at結(jié)束了,此線程才能向下執(zhí)行。
[BThread] Thread start.
[BThread] Thread loop at 0
[BThread] Thread loop at 1
[AThread] Thread start. //線程at啟動(dòng),因?yàn)檎{(diào)用bt.join(),等到bt結(jié)束了才向下執(zhí)行。
[BThread] Thread loop at 2
[BThread] Thread loop at 3
[BThread] Thread loop at 4
[BThread] Thread end.
[AThread] Thread end. // 線程AThread在bt.join();阻塞處起動(dòng),向下繼續(xù)執(zhí)行的結(jié)果
main end! //線程AThread結(jié)束,此線程在at.join();阻塞處起動(dòng),向下繼續(xù)執(zhí)行的結(jié)果。
修改一下代碼:
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(); //在此處注釋掉對(duì)join()的調(diào)用
} catch (Exception e) {
System.out.println("Exception from main");
}
System.out.println(threadName + " end!");
}
}打印結(jié)果:
main start. // 主線程起動(dòng),因?yàn)門hread.sleep(2000),主線程沒有馬上結(jié)束;
[BThread] Thread start. //線程BThread起動(dòng)
[BThread] Thread loop at 0
[BThread] Thread loop at 1
main end! // 在sleep兩秒后主線程結(jié)束,AThread執(zhí)行的bt.join();并不會(huì)影響到主線程。
[AThread] Thread start. //線程at起動(dòng),因?yàn)檎{(diào)用了bt.join(),等到bt結(jié)束了,此線程才向下執(zhí)行。
[BThread] Thread loop at 2
[BThread] Thread loop at 3
[BThread] Thread loop at 4
[BThread] Thread end. //線程BThread結(jié)束了
[AThread] Thread end. // 線程AThread在bt.join();阻塞處起動(dòng),向下繼續(xù)執(zhí)行的結(jié)果
五、從源碼看join()方法
在AThread的run方法里,執(zhí)行了bt.join();,進(jìn)入看一下它的JDK源碼:
public final void join() throws InterruptedException {
join(0L);
}然后進(jìn)入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));
else
do
{
if(!isAlive())
break;
long l3 = l - l2;
if(l3 <= 0L)
break;
wait(l3);
l2 = System.currentTimeMillis() - l1;
} while(true);
}單純從代碼上看: * 如果線程被生成了,但還未被起動(dòng),isAlive()將返回false,調(diào)用它的join()方法是沒有作用的。將直接繼續(xù)向下執(zhí)行。
* 在AThread類中的run方法中,bt.join()是判斷bt的active狀態(tài),如果bt的isActive()方法返回false,在bt.join(),這一點(diǎn)就不用阻塞了,可以繼續(xù)向下進(jìn)行了。
從源碼里看,wait方法中有參數(shù),也就是不用喚醒誰,只是不再執(zhí)行wait,向下繼續(xù)執(zhí)行而已。
* 在join()方法中,對(duì)于isAlive()和wait()方法的作用對(duì)象是個(gè)比較讓人困惑的問題:
isAlive()方法的簽名是:public final native boolean isAlive(),也就是說isAlive()是判斷當(dāng)前線程的狀態(tài),也就是bt的狀態(tài)。
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.
在這里,當(dāng)前線程指的是at。
到此這篇關(guān)于Thread.join()詳解 的文章就介紹到這了,更多相關(guān)Thread.join()詳解 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot使用Spring Test進(jìn)行集成測(cè)試的流程步驟
Spring Test 是 Spring Framework 提供的一個(gè)測(cè)試框架,它可以幫助我們進(jìn)行集成測(cè)試,在本文中,我們將介紹如何使用 Spring Test 進(jìn)行集成測(cè)試,需要的朋友可以參考下2023-06-06
java代碼抓取網(wǎng)頁郵箱的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨ava代碼抓取網(wǎng)頁郵箱的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06
Java實(shí)現(xiàn)圖章或簽名插在pdf的固定位置
使用Java技術(shù)在word轉(zhuǎn)換成pdf過程中實(shí)現(xiàn)將圖章或者簽名插入在pdf中,并生成帶圖章或者簽名的pdf,來完成某些特定場(chǎng)景的需求,文中有詳細(xì)的代碼示例,需要的朋友可以參考下2023-10-10
Java中outer標(biāo)簽的用法實(shí)例代碼
這篇文章主要介紹了Java中outer標(biāo)簽的用法,在這里需要大家注意這里的outer并不是關(guān)鍵字,而僅僅是一個(gè)標(biāo)簽,本文結(jié)合實(shí)例代碼給大家詳細(xì)講解,需要的朋友可以參考下2023-01-01
SSM項(xiàng)目實(shí)現(xiàn)短信驗(yàn)證碼登錄功能的示例代碼
這篇文章主要為大家分享了在SSM項(xiàng)目中實(shí)現(xiàn)短信驗(yàn)證碼登錄功能的示例代碼,文中的實(shí)現(xiàn)步驟講解詳細(xì),感興趣的小伙伴可以跟隨小編一起動(dòng)手嘗試一下2022-05-05
SpringBoot整合easyExcel實(shí)現(xiàn)CSV格式文件的導(dǎo)入導(dǎo)出
這篇文章主要為大家詳細(xì)介紹了SpringBoot整合easyExcel實(shí)現(xiàn)CSV格式文件的導(dǎo)入導(dǎo)出,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴可以參考下2024-02-02
Java使用EasyExcel實(shí)現(xiàn)Excel的導(dǎo)入導(dǎo)出
這篇文章主要給大家介紹了關(guān)于Java使用EasyExcel實(shí)現(xiàn)Excel的導(dǎo)入導(dǎo)出,在各種系統(tǒng)中,導(dǎo)入導(dǎo)出的數(shù)據(jù)一般都是通過Excel來完成的,需要的朋友可以參考下2023-07-07

