JAVA多線程之方法 JOIN詳解及實(shí)例代碼
JAVA多線程 JOIN
對(duì)于Java開(kāi)發(fā)人員,多線程應(yīng)該是必須熟練應(yīng)用的知識(shí)點(diǎn),特別是開(kāi)發(fā)基于Java語(yǔ)言的產(chǎn)品。本文將深入淺出的表述Java多線程的知識(shí)點(diǎn),在后續(xù)的系列里將側(cè)重于Java5由Doug Lea教授提供的Concurrent并行包的設(shè)計(jì)思想以及具體實(shí)現(xiàn)與應(yīng)用。
如何才能深入淺出呢,我的理解是帶著問(wèn)題,而不是泛泛的看。所以該系列基本以解決問(wèn)題為主,當(dāng)然我也非常希望讀者能夠提出更好的解決問(wèn)題的方案以及提出更多的問(wèn)題。由于水平有限,如果有什么錯(cuò)誤之處,請(qǐng)大家提出,共同討論,總之,我希望通過(guò)該系列我們能夠深入理解Java多線程來(lái)解決我們實(shí)際開(kāi)發(fā)的問(wèn)題。
作為開(kāi)發(fā)人員,我想沒(méi)有必要討論多線程的基礎(chǔ)知識(shí),比如什么是線程? 如何創(chuàng)建等 ,這些知識(shí)點(diǎn)是可以通過(guò)書(shū)本和Google獲得的。本系列主要是如何理深入解多線程來(lái)幫助我們平時(shí)的開(kāi)發(fā),比如線程池如何實(shí)現(xiàn)? 如何應(yīng)用鎖等。
(1)方法Join是干啥用的? 簡(jiǎn)單回答,同步,如何同步? 怎么實(shí)現(xiàn)的? 下面將逐個(gè)回答。
自從接觸Java多線程,一直對(duì)Join理解不了。JDK是這樣說(shuō)的:
join public final void join(long millis)throws InterruptedException Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
大家能理解嗎? 字面意思是等待一段時(shí)間直到這個(gè)線程死亡,我的疑問(wèn)是那個(gè)線程,是它本身的線程還是調(diào)用它的線程的,上代碼:
package concurrentstudy; /** * * @author vma */ public class JoinTest { public static void main(String[] args) { Thread t = new Thread(new RunnableImpl()); t.start(); try { t.join(1000); System.out.println("joinFinish"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class RunnableImpl implements Runnable { @Override public void run() { try { System.out.println("Begin sleep"); Thread.sleep(1000); System.out.println("End sleep"); } catch (InterruptedException e) { e.printStackTrace(); } } }
結(jié)果是:
Begin sleep End sleep joinFinish
明白了吧,當(dāng)main線程調(diào)用t.join時(shí),main線程等待t線程,等待時(shí)間是1000,如果t線程Sleep 2000呢
public void run() { try { System.out.println("Begin sleep"); // Thread.sleep(1000); Thread.sleep(2000); System.out.println("End sleep"); } catch (InterruptedException e) { e.printStackTrace(); } }
結(jié)果是:
Begin sleep joinFinish End sleep
也就是說(shuō)main線程只等1000毫秒,不管T什么時(shí)候結(jié)束,如果是t.join()呢, 看代碼:
public final void join() throws InterruptedException { join(0); }
就是說(shuō)如果是t.join() = t.join(0) 0 JDK這樣說(shuō)的 A timeout of 0 means to wait forever 字面意思是永遠(yuǎn)等待,是這樣嗎?
其實(shí)是等到t結(jié)束后。
這個(gè)是怎么實(shí)現(xiàn)的嗎? 看JDK代碼:
/** * Waits at most <code>millis</code> milliseconds for this thread to * die. A timeout of <code>0</code> means to wait forever. * * @param millis the time to wait in milliseconds. * @exception InterruptedException if any thread has interrupted * the current thread. The <i>interrupted status</i> of the * current thread is cleared when this exception is thrown. */ 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; } } }
其實(shí)Join方法實(shí)現(xiàn)是通過(guò)wait(小提示:Object 提供的方法)。 當(dāng)main線程調(diào)用t.join時(shí)候,main線程會(huì)獲得線程對(duì)象t的鎖(wait 意味著拿到該對(duì)象的鎖),調(diào)用該對(duì)象的wait(等待時(shí)間),直到該對(duì)象喚醒main線程,比如退出后。
這就意味著main 線程調(diào)用t.join時(shí),必須能夠拿到線程t對(duì)象的鎖,如果拿不到它是無(wú)法wait的,剛開(kāi)的例子t.join(1000)不是說(shuō)明了main線程等待1秒,如果在它等待之前,其他線程獲取了t對(duì)象的鎖,它等待時(shí)間可不就是1毫秒了。上代碼介紹:
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package concurrentstudy; /** * * @author vma */ public class JoinTest { public static void main(String[] args) { Thread t = new Thread(new RunnableImpl()); new ThreadTest(t).start(); t.start(); try { t.join(); System.out.println("joinFinish"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class ThreadTest extends Thread { Thread thread; public ThreadTest(Thread thread) { this.thread = thread; } @Override public void run() { holdThreadLock(); } public void holdThreadLock() { synchronized (thread) { System.out.println("getObjectLock"); try { Thread.sleep(9000); } catch (InterruptedException ex) { ex.printStackTrace(); } System.out.println("ReleaseObjectLock"); } } } class RunnableImpl implements Runnable { @Override public void run() { try { System.out.println("Begin sleep"); Thread.sleep(2000); System.out.println("End sleep"); } catch (InterruptedException e) { e.printStackTrace(); } } }
在main方法中 通過(guò)new ThreadTest(t).start();實(shí)例化ThreadTest 線程對(duì)象, 它在holdThreadLock()方法中,通過(guò)synchronized (thread),獲取線程對(duì)象t的鎖,并Sleep(9000)后釋放,這就意味著,即使main方法t.join(1000),等待一秒鐘,它必須等待ThreadTest 線程釋放t鎖后才能進(jìn)入wait方法中,它實(shí)際等待時(shí)間是9000+1000 MS
運(yùn)行結(jié)果是:
getObjectLock Begin sleep End sleep ReleaseObjectLock joinFinish
小結(jié):
本節(jié)主要深入淺出join及JDK中的實(shí)現(xiàn)。
感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
相關(guān)文章
淺談Springboot之于Spring的優(yōu)勢(shì)
這篇文章主要介紹了淺談Springboot之于Spring的優(yōu)勢(shì),簡(jiǎn)述了在Java EE開(kāi)發(fā)中遇到的問(wèn)題,言簡(jiǎn)意賅,需要的朋友可以參考下。2017-09-09java ThreadPool線程池的使用,線程池工具類(lèi)用法說(shuō)明
這篇文章主要介紹了java ThreadPool線程池的使用,線程池工具類(lèi)用法說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10Eclipse+Java+Swing實(shí)現(xiàn)斗地主游戲(代碼)
這篇文章主要介紹了Eclipse+Java+Swing實(shí)現(xiàn)斗地主游戲并附上詳細(xì)的代碼實(shí)現(xiàn),正在學(xué)習(xí)的你可以當(dāng)小練習(xí)練練,希望對(duì)你有所幫助2022-01-01深度源碼解析Java 線程池的實(shí)現(xiàn)原理
如何高效的使用這些資源就是程序員在平時(shí)寫(xiě)代碼時(shí)候的一個(gè)努力的方向。本文要說(shuō)的線程池就是一種對(duì) CPU 利用的優(yōu)化手段。對(duì)Java 線程池的實(shí)現(xiàn)原理相關(guān)知識(shí)感興趣的朋友一起看看吧2021-05-05Java File類(lèi)的詳解及簡(jiǎn)單實(shí)例
這篇文章主要介紹了Java File類(lèi)的詳解及簡(jiǎn)單實(shí)例的相關(guān)資料,希望通過(guò)本文大家能夠掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09