java方法中 thread,Java中的線程Thread方法之---join()
上一篇我們說到了Thread中的stop方法,這一篇我們再來看一下方法join的使用,那么方法Join是干啥用的? 簡單回答,同步,如何同步? 怎么實現的? 下面將逐個回答。
join方法從字面上的意思就是加入到一個線程中,這樣就可以很好的進行線程之間的交互運行了,不多說先來看一下代碼:
package com.threadjoin.demo;
public class ThreadJoin {
public static int a = 0;
public static void main(String[] args){
Thread thread = new Thread(new Runnable(){
@Override
public void run(){
for(int i=0;i<5;i++)
a++;
}
});
thread.start();
/*try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}*/
System.out.println(a);
}
}
運行代碼,貌似永遠都看不到a的值是5,而每次都是0,原因很簡單的,因為在thread中的run方法中進行a的增值操作,這些可能都是需要時間的,但是此時main線程中的System.out.println方法已經執行了,所以很難看到a的值是5,為了看到a的值是5,我的一個思路就是等thread運行結束之后,我們采取執行System.out.println就可以了,這時候join方法的作用就顯現出來的,我們把上面的注釋代碼刪除注釋,然后運行,不管運行多少次,輸出的結果都是5,從這個例子中我們就可以看到join方法的作用,它能夠調節各個線程之間的運行順序,從而可以實現同步。為了更好的了解join的運行原理我們只有看他的源碼了:
publicfinalvoidjoin()throwsInterruptedException?{
join(0);
}
我們在跟蹤到join(0)方法中:
//方法是個同步的,而且會拋出InterruptedException異常
publicfinalsynchronizedvoidjoin(longmillis)throwsInterruptedException?{
longbase?=?System.currentTimeMillis();
longnow?=0;
if(millis?<0)?{
thrownewIllegalArgumentException("timeout?value?is?negative");
}
//我們可以看到這里使用了while循環做判斷的,然后調用wait方法的,所以說join方法的執行是完全通過wait方法實現的
//等待時間為0的時候,就是無限等待,直到線程死亡了(即線程執行完了)
if(millis?==0)?{
//如果當前線程還存活的話,就等待
while(isAlive())?{
//調用該線程的join方法的線程拿到鎖之后進行等待,直到線程執行結束(這個例子就是main線程)
wait(0);
}
}?else{
//如果是等待的特定時間的話
while(isAlive())?{
longdelay?=?millis?-?now;
if(delay?<=0)?{
break;
}
wait(delay);
now?=?System.currentTimeMillis()?-?base;
}
}
}
從代碼中我們可以看到join方法是個同步的,這個我們后面會做個例子,然后進入到方法中我們可以看到,有兩種情況,一種是等待時間是0的,其實就等同無線等待,直到線程執行結束了,還有一種就是要等待的是一定的時間,原理都是一樣的,
看完源碼之后我們在看一一個例子:
packagecom.threadjoin.demo;
/**
*
其實Join方法實現是通過wait(小提示:Object?提供的方法)。
當main線程調用t.join時候,main線程會獲得線程對象t的鎖(wait意味著拿到該對象的鎖),
調用該對象的wait(等待時間),直到該對象喚醒main線程,比如退出后。
這就意味著main?線程調用t.join時,
必須能夠拿到線程t對象的鎖,如果拿不到它是無法wait的,剛開的例子t.join(1000)不是說明了main線程等待1秒,
如果在它等待之前,其他線程獲取了t對象的鎖,它等待時間可不就是1秒了
*?@author?weijiang204321
*
*/
publicclassThreadJoinTest?{
publicstaticvoidmain(String[]?args)?{
Thread?t?=?newThread(newRunnableImpl());
newThreadTest(t).start();
t.start();
try{
t.join(1000);
System.out.println("joinFinish");
}?catch(InterruptedException?e)?{
e.printStackTrace();
}
}
}
classRunnableImplimplementsRunnable?{
@Override
publicvoidrun()?{
try{
System.out.println("Begin?sleep");
Thread.sleep(1000);
System.out.println("End?sleep");
}?catch(InterruptedException?e)?{
e.printStackTrace();
}
}
}
classThreadTestextendsThread?{
Thread?thread;
publicThreadTest(Thread?thread)?{
this.thread?=?thread;
}
@Override
publicvoidrun()?{
holdThreadLock();
}
publicvoidholdThreadLock()?{
//用當前的線程當做lock
synchronized(thread)?{
System.out.println("getObjectLock");
try{
Thread.sleep(9*1000);
}?catch(InterruptedException?ex)?{
ex.printStackTrace();
}
System.out.println("ReleaseObjectLock");
}
}
}
在main方法中通過new??ThreadTest(t).start()實例化?ThreadTest?線程對象, 它?通過?synchronized??(thread)?,獲取線程對象t的鎖,並sleep(9*1000)后釋放,因為我們上面看到了join方法是個同步的,而且同步鎖是當前的線程對象,因為ThreadTest先運行的,首先拿到了線程t對象的鎖,所以join方法還沒有拿到鎖,所以要等待。這就意味著,即使main方法t.join(1000)等待一秒鍾,它必須等待ThreadTest?線程釋放t鎖后才能進入wait方法中,它實際等待時間是9000+1000ms=10s。
總結
以上是生活随笔為你收集整理的java方法中 thread,Java中的線程Thread方法之---join()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php 5.3.3 漏洞,PHP 5.3
- 下一篇: java面向对象编程考试题,202514