java 線程方法join簡(jiǎn)單用法實(shí)例總結(jié)
本文實(shí)例講述了java 線程方法join簡(jiǎn)單用法。分享給大家供大家參考,具體如下:
雖然關(guān)于討論線程join方法的博客已經(jīng)很多了,不過個(gè)人感覺挺多都討論得不夠全面,所以我覺得有必要對(duì)其進(jìn)行一個(gè)全面的總結(jié)。
一、作用
Thread類中的join方法的主要作用就是同步,它可以使得線程之間的并行執(zhí)行變?yōu)榇袌?zhí)行。具體看代碼:
public class JoinTest { public static void main(String [] args) throws InterruptedException { ThreadJoinTest t1 = new ThreadJoinTest("小明"); ThreadJoinTest t2 = new ThreadJoinTest("小東"); t1.start(); /**join的意思是使得放棄當(dāng)前線程的執(zhí)行,并返回對(duì)應(yīng)的線程,例如下面代碼的意思就是: 程序在main線程中調(diào)用t1線程的join方法,則main線程放棄cpu控制權(quán),并返回t1線程繼續(xù)執(zhí)行直到線程t1執(zhí)行完畢 所以結(jié)果是t1線程執(zhí)行完后,才到主線程執(zhí)行,相當(dāng)于在main線程中同步t1線程,t1執(zhí)行完了,main線程才有執(zhí)行的機(jī)會(huì) */ t1.join(); t2.start(); } } class ThreadJoinTest extends Thread{ public ThreadJoinTest(String name){ super(name); } @Override public void run(){ for(int i=0;i<1000;i++){ System.out.println(this.getName() + ":" + i); } } }
上面程序結(jié)果是先打印完小明線程,在打印小東線程;
上面注釋也大概說明了join方法的作用:在A線程中調(diào)用了B線程的join()方法時(shí),表示只有當(dāng)B線程執(zhí)行完畢時(shí),A線程才能繼續(xù)執(zhí)行。注意,這里調(diào)用的join方法是沒有傳參的,join方法其實(shí)也可以傳遞一個(gè)參數(shù)給它的,具體看下面的簡(jiǎn)單例子:
public class JoinTest { public static void main(String [] args) throws InterruptedException { ThreadJoinTest t1 = new ThreadJoinTest("小明"); ThreadJoinTest t2 = new ThreadJoinTest("小東"); t1.start(); /**join方法可以傳遞參數(shù),join(10)表示main線程會(huì)等待t1線程10毫秒,10毫秒過去后, * main線程和t1線程之間執(zhí)行順序由串行執(zhí)行變?yōu)槠胀ǖ牟⑿袌?zhí)行 */ t1.join(10); t2.start(); } } class ThreadJoinTest extends Thread{ public ThreadJoinTest(String name){ super(name); } @Override public void run(){ for(int i=0;i<1000;i++){ System.out.println(this.getName() + ":" + i); } } }
上面代碼結(jié)果是:程序執(zhí)行前面10毫秒內(nèi)打印的都是小明線程,10毫秒后,小明和小東程序交替打印。
所以,join方法中如果傳入?yún)?shù),則表示這樣的意思:如果A線程中掉用B線程的join(10),則表示A線程會(huì)等待B線程執(zhí)行10毫秒,10毫秒過后,A、B線程并行執(zhí)行。需要注意的是,jdk規(guī)定,join(0)的意思不是A線程等待B線程0秒,而是A線程等待B線程無限時(shí)間,直到B線程執(zhí)行完畢,即join(0)等價(jià)于join()。
二、join與start調(diào)用順序問題
上面的討論大概知道了join的作用了,那么,入股 join在start前調(diào)用,會(huì)出現(xiàn)什么后果呢?先看下面的測(cè)試結(jié)果
public class JoinTest { public static void main(String [] args) throws InterruptedException { ThreadJoinTest t1 = new ThreadJoinTest("小明"); ThreadJoinTest t2 = new ThreadJoinTest("小東"); /**join方法可以在start方法前調(diào)用時(shí),并不能起到同步的作用 */ t1.join(); t1.start(); //Thread.yield(); t2.start(); } } class ThreadJoinTest extends Thread{ public ThreadJoinTest(String name){ super(name); } @Override public void run(){ for(int i=0;i<1000;i++){ System.out.println(this.getName() + ":" + i); } } }
上面代碼執(zhí)行結(jié)果是:小明和小東線程交替打印。
所以得到以下結(jié)論:join方法必須在線程start方法調(diào)用之后調(diào)用才有意義。這個(gè)也很容易理解:如果一個(gè)線程都沒有start,那它也就無法同步了。
三、join方法實(shí)現(xiàn)原理
有了上面的例子,我們大概知道join方法的作用了,那么,join方法實(shí)現(xiàn)的原理是什么呢?
其實(shí),join方法是通過調(diào)用線程的wait方法來達(dá)到同步的目的的。例如,A線程中調(diào)用了B線程的join方法,則相當(dāng)于A線程調(diào)用了B線程的wait方法,在調(diào)用了B線程的wait方法后,A線程就會(huì)進(jìn)入阻塞狀態(tài),具體看下面的源碼:
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; } } }
從源碼中可以看到:join方法的原理就是調(diào)用相應(yīng)線程的wait方法進(jìn)行等待操作的,例如A線程中調(diào)用了B線程的join方法,則相當(dāng)于在A線程中調(diào)用了B線程的wait方法,當(dāng)B線程執(zhí)行完(或者到達(dá)等待時(shí)間),B線程會(huì)自動(dòng)調(diào)用自身的notifyAll方法喚醒A線程,從而達(dá)到同步的目的。
更多java相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java進(jìn)程與線程操作技巧總結(jié)》、《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
一個(gè)MIDP俄羅斯方塊游戲的設(shè)計(jì)和實(shí)現(xiàn)
一個(gè)MIDP俄羅斯方塊游戲的設(shè)計(jì)和實(shí)現(xiàn)...2006-12-12IDE Eval Reset忘了重置進(jìn)不去的完美解決方法
這篇文章主要介紹了IDE Eval Reset忘了重置進(jìn)不去的完美解決方法,插件安裝方式包括離線安裝和在線安裝方式,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-12-12歸并算法之有序數(shù)組合并算法實(shí)現(xiàn)
這篇文章主要介紹了歸并算法之有序數(shù)組合并算法實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2017-07-07利用Java將2019拆分成三個(gè)素?cái)?shù)平方和的方法實(shí)例
這篇文章主要給大家介紹了關(guān)于利用Java將2019拆分成三個(gè)素?cái)?shù)平方和的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Java微信支付之公眾號(hào)支付、掃碼支付實(shí)例
微信支付已經(jīng)成為生活中必不可少的付款方式,本篇文章主要介紹了Java微信支付之公眾號(hào)支付、掃碼支付,有需要的小伙伴可以了解一下。2016-11-11Spring mvc是如何實(shí)現(xiàn)與數(shù)據(jù)庫的前后端的連接操作的?
今天給大家?guī)淼氖顷P(guān)于Spring mvc的相關(guān)知識(shí),文章圍繞著Spring mvc是如何實(shí)現(xiàn)與數(shù)據(jù)庫的前后端的連接操作的展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06詳解SpringBoot如何創(chuàng)建自定義Starter
Spring Boot的自動(dòng)配置機(jī)制為開發(fā)人員提供了一種輕松集成和配置各種功能的便捷方式,本文將深入探討在Spring Boot中如何創(chuàng)建自定義Starter,為構(gòu)建模塊化且易維護(hù)的應(yīng)用提供有力的支持,需要的朋友可以參考下2024-02-02關(guān)于Spring多數(shù)據(jù)源TransactionManager沖突的解決方案
這篇文章主要介紹了關(guān)于Spring多數(shù)據(jù)源TransactionManager沖突的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07