Java線程中wait蔚万、await岭妖、sleep、yield、join用法總結(jié)

一昵慌、wait()假夺、notify()、notifyAll()用法

obj.wait()/obj.wait(long timeout)是Object中的方法斋攀,當線程調(diào)用wait()方法已卷,當前線程釋放對象鎖,進入等待隊列淳蔼。

obj.notify()/obj.nogifyAll()是Object中的方法侧蘸,喚醒在此對象上wait()的單個或者所有線程。

測試代碼:

public class ThreadWaitNotify {

    public static void main(String[] args) throws InterruptedException {
        //創(chuàng)建一個線程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        //創(chuàng)建DemoTest對象
        DemoTest demoTest = new DemoTest();
        //用線程池創(chuàng)建線程異步執(zhí)行waitTest方法
        executorService.submit(() -> demoTest.waitTest());
        //用線程池創(chuàng)建線程異步執(zhí)行notifyTest方法
        executorService.submit(() -> demoTest.notifyTest());
    }

    //測試wait和notify測試demo
    static class DemoTest {
        //喚醒線程
        public synchronized void notifyTest() {
            System.out.println("方法notifyTest開始執(zhí)行了");
            notify();
            System.out.println("方法notifyTest執(zhí)行結(jié)束了");
        }
        //執(zhí)行wait操作將線程掛起鹉梨,注意必須結(jié)合synchronized使用
        public synchronized void waitTest() {
            System.out.println("方法waitTest開始執(zhí)行了");
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("方法waitTest執(zhí)行結(jié)束了");
        }
    }
}

打印日志:

方法waitTest開始執(zhí)行了
方法notifyTest開始執(zhí)行了
方法notifyTest執(zhí)行結(jié)束了
方法waitTest執(zhí)行結(jié)束了

從日志中我們可以看出waitTest方法阻塞直到被notifyTest喚醒

二讳癌、await()、signal()存皂、signalAll()用法

java.util.concurrent類庫中提供的Condition類來實現(xiàn)線程之間的協(xié)調(diào)晌坤。

condition.await()/condition.await(long time, TimeUnit unit):通過condition調(diào)用,當前線程釋放對象鎖旦袋。

condition.signal()/condition.signalAll():通過signal或者signalAll方法喚醒await掛起的線程骤菠。

測試代碼:

public class ThreadAwaitSignal {
    public static void main(String[] args) {
        //創(chuàng)建一個線程池
        ExecutorService executorService = Executors.newCachedThreadPool();
        //創(chuàng)建DemoTest對象
        DemoTest demoTest = new DemoTest();
        //用線程池創(chuàng)建線程異步執(zhí)行awaitTest方法
        executorService.submit(() -> demoTest.awaitTest());
        //用線程池創(chuàng)建線程異步執(zhí)行signalTest方法
        executorService.submit(() -> demoTest.signalTest());
    }

    /**
     * 使用java.util.conncurrent類中提供了Condition類來實現(xiàn)線程之間的協(xié)調(diào)
     * 可以在Condition上調(diào)用await()方法使線程掛起
     * 其他線程調(diào)用signal()或者signalAll()來喚醒線程
     */
    static class DemoTest {
        //定義一個Lock對象用來獲取Condition對象
        private Lock lock = new ReentrantLock();
        private Condition condition = lock.newCondition();
        //喚醒線程
        public void signalTest() {
            lock.lock();
            try {
                System.out.println("方法signalTest開始執(zhí)行了");
                condition.signalAll();
                System.out.println("方法signalTest執(zhí)行結(jié)束了");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }

        //結(jié)合lock鎖實現(xiàn)Condition的await
        public void awaitTest() {
            lock.lock();
            try {
                System.out.println("方法awaitTest開始執(zhí)行了");
                condition.await();
                System.out.println("方法awaitTest執(zhí)行結(jié)束了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }
    }
}

打印日志:

方法awaitTest開始執(zhí)行了
方法signalTest開始執(zhí)行了
方法signalTest執(zhí)行結(jié)束了
方法awaitTest執(zhí)行結(jié)束了

從日志中國可以看出我們得到了和wait同樣的效果。

三 疤孕、yield()商乎、join()用法

Thread.yield():一定是當前線程調(diào)用此方法,當前線程放棄獲取CPU的時間片胰柑,由運行態(tài)轉(zhuǎn)變?yōu)榫途w態(tài)截亦,讓操作系統(tǒng)中再次選擇線程執(zhí)行爬泥。作用:讓相同優(yōu)先級的線程輪流執(zhí)行柬讨,但并不能保證輪流執(zhí)行,根據(jù)解釋我們了解到袍啡,轉(zhuǎn)成就緒態(tài)的的線程還有可能再次選中執(zhí)行踩官。Thread.yield()方法不會導致阻塞。

t.join()/t.join(long millis):當前線程調(diào)用t2.join()方法境输,當前線程阻塞但是不會釋放對象鎖蔗牡,直到t2線程執(zhí)行完畢或者millis時間到,則當前的線程恢復就緒狀態(tài)嗅剖。作用:讓優(yōu)先級比較高的線程優(yōu)先執(zhí)行辩越。

yield測試代碼:

    //yield放棄CPU時間片
    public static void yieldTest(){
        //定義一個線程
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ": 測試線程開始執(zhí)行。信粮。黔攒。");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ": 測試線程執(zhí)行結(jié)束了。");
        });
        thread.start();
        System.out.println(Thread.currentThread().getName() + ": 執(zhí)行yield方法");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + ": 主線程開始執(zhí)行");
    }

打印結(jié)果:

main: 執(zhí)行yield方法
main: 主線程開始執(zhí)行
Thread-0: 測試線程開始執(zhí)行。督惰。不傅。
Thread-0: 測試線程執(zhí)行結(jié)束了。

可以看出雖然主線程調(diào)用了yield赏胚,但是仍然又開始執(zhí)行了访娶,因此但并不能保證輪流執(zhí)行。

join測試代碼:

   //join搶占CPU時間片
    public static void joinTest() throws InterruptedException {
        //定義一個線程
        Thread thread = new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + ": 測試線程開始執(zhí)行觉阅。崖疤。。");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + ": 測試線程執(zhí)行結(jié)束了典勇。");
        });
        thread.start();
        System.out.println(thread.getName() + ": 執(zhí)行join方法");
        thread.join();
        System.out.println(Thread.currentThread().getName() + ": 主線程開始執(zhí)行");
    }

打印日志:

Thread-0: 執(zhí)行join方法
Thread-0: 測試線程開始執(zhí)行戳晌。。痴柔。
Thread-0: 測試線程執(zhí)行結(jié)束了沦偎。
main: 主線程開始執(zhí)行

從日志中我們可以看出主線程在線程執(zhí)行完成后才開始執(zhí)行。

四咳蔚、wait()豪嚎、await()、sleep()谈火、yield侈询、join對比

通過表格對比(join的情況下,t1指代當前線程糯耍,t2代表其他線程)


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末扔字,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子温技,更是在濱河造成了極大的恐慌革为,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舵鳞,死亡現(xiàn)場離奇詭異震檩,居然都是意外死亡,警方通過查閱死者的電腦和手機蜓堕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進店門抛虏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人套才,你說我怎么就攤上這事迂猴。” “怎么了背伴?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵沸毁,是天一觀的道長儡率。 經(jīng)常有香客問我,道長以清,這世上最難降的妖魔是什么儿普? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮掷倔,結(jié)果婚禮上眉孩,老公的妹妹穿的比我還像新娘。我一直安慰自己勒葱,他們只是感情好浪汪,可當我...
    茶點故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凛虽,像睡著了一般死遭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上凯旋,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天呀潭,我揣著相機與錄音,去河邊找鬼至非。 笑死钠署,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的荒椭。 我是一名探鬼主播谐鼎,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼趣惠!你這毒婦竟也來了狸棍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤味悄,失蹤者是張志新(化名)和其女友劉穎草戈,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體傍菇,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡猾瘸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了丢习。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡淮悼,死狀恐怖咐低,靈堂內(nèi)的尸體忽然破棺而出袜腥,到底是詐尸還是另有隱情见擦,我是刑警寧澤钉汗,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站鲤屡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏卢未。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望汉匙。 院中可真熱鬧生蚁,春花似錦、人聲如沸绎秒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽徘铝。三九已至惯吕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淹魄,已是汗流浹背甲锡。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工缤沦, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缸废,地道東北人养晋。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓绳泉,卻偏偏與公主長得像姆泻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子四苇,可洞房花燭夜當晚...
    茶點故事閱讀 43,566評論 2 349