亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

java基本教程之java線程等待與java喚醒線程 java多線程教程

2019-11-26 15:46:56
字體:
來源:轉載
供稿:網友

本章,會對線程等待/喚醒方法進行介紹。涉及到的內容包括:
1. wait(), notify(), notifyAll()等方法介紹
2. wait()和notify()
3. wait(long timeout)和notify()
4. wait() 和 notifyAll()
5. 為什么notify(), wait()等函數定義在Object中,而不是Thread中

wait(), notify(), notifyAll()等方法介紹
在Object.java中,定義了wait(), notify()和notifyAll()等接口。wait()的作用是讓當前線程進入等待狀態,同時,wait()也會讓當前線程釋放它所持有的鎖。而notify()和notifyAll()的作用,則是喚醒當前對象上的等待線程;notify()是喚醒單個線程,而notifyAll()是喚醒所有的線程。

Object類中關于等待/喚醒的API詳細信息如下:
notify()        -- 喚醒在此對象監視器上等待的單個線程。
notifyAll()   -- 喚醒在此對象監視器上等待的所有線程。
wait()                                         -- 讓當前線程處于“等待(阻塞)狀態”,“直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法”,當前線程被喚醒(進入“就緒狀態”)。
wait(long timeout)                    -- 讓當前線程處于“等待(阻塞)狀態”,“直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量”,當前線程被喚醒(進入“就緒狀態”)。
wait(long timeout, int nanos)  -- 讓當前線程處于“等待(阻塞)狀態”,“直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法,或者其他某個線程中斷當前線程,或者已超過某個實際時間量”,當前線程被喚醒(進入“就緒狀態”)。


2. wait()和notify()示例
下面通過示例演示"wait()和notify()配合使用的情形"。

復制代碼 代碼如下:

// WaitTest.java的源碼
class ThreadA extends Thread{

    public ThreadA(String name) {
        super(name);
    }

    public void run() {
        synchronized (this) {
            System.out.println(Thread.currentThread().getName()+" call notify()");
            // 喚醒當前的wait線程
            notify();
        }
    }
}

public class WaitTest {

    public static void main(String[] args) {

        ThreadA t1 = new ThreadA("t1");

        synchronized(t1) {
            try {
                // 啟動“線程t1”
                System.out.println(Thread.currentThread().getName()+" start t1");
                t1.start();

                // 主線程等待t1通過notify()喚醒。
                System.out.println(Thread.currentThread().getName()+" wait()");
                t1.wait();

                System.out.println(Thread.currentThread().getName()+" continue");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

運行結果:

復制代碼 代碼如下:

main start t1
main wait()
t1 call notify()
main continue

結果說明:
如下圖,說明了“主線程”和“線程t1”的流程。

(01) 注意,圖中"主線程" 代表“主線程main”。"線程t1" 代表WaitTest中啟動的“線程t1”。 而“鎖” 代表“t1這個對象的同步鎖”。
(02) “主線程”通過 new ThreadA("t1") 新建“線程t1”。隨后通過synchronized(t1)獲取“t1對象的同步鎖”。然后調用t1.start()啟動“線程t1”。
(03) “主線程”執行t1.wait() 釋放“t1對象的鎖”并且進入“等待(阻塞)狀態”。等待t1對象上的線程通過notify() 或 notifyAll()將其喚醒。
(04) “線程t1”運行之后,通過synchronized(this)獲取“當前對象的鎖”;接著調用notify()喚醒“當前對象上的等待線程”,也就是喚醒“主線程”。
(05) “線程t1”運行完畢之后,釋放“當前對象的鎖”。緊接著,“主線程”獲取“t1對象的鎖”,然后接著運行。


對于上面的代碼?曾經有個朋友問到過:t1.wait()應該是讓“線程t1”等待;但是,為什么卻是讓“主線程main”等待了呢?
在解答該問題前,我們先看看jdk文檔中關于wait的一段介紹:

復制代碼 代碼如下:

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.

中文意思大概是:

引起“當前線程”等待,直到另外一個線程調用notify()或notifyAll()喚醒該線程。換句話說,這個方法和wait(0)的效果一樣!(補充,對于wait(long millis)方法,當millis為0時,表示無限等待,直到被notify()或notifyAll()喚醒)。
“當前線程”在調用wait()時,必須擁有該對象的同步鎖。該線程調用wait()之后,會釋放該鎖;然后一直等待直到“其它線程”調用對象的同步鎖的notify()或notifyAll()方法。然后,該線程繼續等待直到它重新獲取“該對象的同步鎖”,然后就可以接著運行。
注意:jdk的解釋中,說wait()的作用是讓“當前線程”等待,而“當前線程”是指正在cpu上運行的線程!
這也意味著,雖然t1.wait()是通過“線程t1”調用的wait()方法,但是調用t1.wait()的地方是在“主線程main”中。而主線程必須是“當前線程”,也就是運行狀態,才可以執行t1.wait()。所以,此時的“當前線程”是“主線程main”!因此,t1.wait()是讓“主線程”等待,而不是“線程t1”!


3. wait(long timeout)和notify()
wait(long timeout)會讓當前線程處于“等待(阻塞)狀態”,“直到其他線程調用此對象的 notify() 方法或 notifyAll() 方法,或者超過指定的時間量”,當前線程被喚醒(進入“就緒狀態”)。
下面的示例就是演示wait(long timeout)在超時情況下,線程被喚醒的情況。

復制代碼 代碼如下:

// WaitTimeoutTest.java的源碼
class ThreadA extends Thread{

    public ThreadA(String name) {
        super(name);
    }

    public void run() {
        System.out.println(Thread.currentThread().getName() + " run ");
        // 死循環,不斷運行。
        while(true)

    }
}

public class WaitTimeoutTest {

    public static void main(String[] args) {

        ThreadA t1 = new ThreadA("t1");

        synchronized(t1) {
            try {
                // 啟動“線程t1”
                System.out.println(Thread.currentThread().getName() + " start t1");
                t1.start();

                // 主線程等待t1通過notify()喚醒 或 notifyAll()喚醒,或超過3000ms延時;然后才被喚醒。
                System.out.println(Thread.currentThread().getName() + " call wait ");
                t1.wait(3000);

                System.out.println(Thread.currentThread().getName() + " continue");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

運行結果:

復制代碼 代碼如下:

main start t1
main call wait
t1 run                  // 大約3秒之后...輸出“main continue”
main continue

結果說明:
如下圖,說明了“主線程”和“線程t1”的流程。
(01) 注意,圖中"主線程" 代表WaitTimeoutTest主線程(即,線程main)。"線程t1" 代表WaitTest中啟動的線程t1。 而“鎖” 代表“t1這個對象的同步鎖”。
(02) 主線程main執行t1.start()啟動“線程t1”。
(03) 主線程main執行t1.wait(3000),此時,主線程進入“阻塞狀態”。需要“用于t1對象鎖的線程通過notify() 或者 notifyAll()將其喚醒” 或者 “超時3000ms之后”,主線程main才進入到“就緒狀態”,然后才可以運行。
(04) “線程t1”運行之后,進入了死循環,一直不斷的運行。
(05) 超時3000ms之后,主線程main會進入到“就緒狀態”,然后接著進入“運行狀態”。

4. wait() 和 notifyAll()
通過前面的示例,我們知道 notify() 可以喚醒在此對象監視器上等待的單個線程。
下面,我們通過示例演示notifyAll()的用法;它的作用是喚醒在此對象監視器上等待的所有線程。

復制代碼 代碼如下:

public class NotifyAllTest {

    private static Object obj = new Object();
    public static void main(String[] args) {

        ThreadA t1 = new ThreadA("t1");
        ThreadA t2 = new ThreadA("t2");
        ThreadA t3 = new ThreadA("t3");
        t1.start();
        t2.start();
        t3.start();

        try {
            System.out.println(Thread.currentThread().getName()+" sleep(3000)");
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized(obj) {
            // 主線程等待喚醒。
            System.out.println(Thread.currentThread().getName()+" notifyAll()");
            obj.notifyAll();
        }
    }

    static class ThreadA extends Thread{

        public ThreadA(String name){
            super(name);
        }

        public void run() {
            synchronized (obj) {
                try {
                    // 打印輸出結果
                    System.out.println(Thread.currentThread().getName() + " wait");

                    // 喚醒當前的wait線程
                    obj.wait();

                    // 打印輸出結果
                    System.out.println(Thread.currentThread().getName() + " continue");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

運行結果:

復制代碼 代碼如下:

t1 wait
main sleep(3000)
t3 wait
t2 wait
main notifyAll()
t2 continue
t3 continue
t1 continue

結果說明:
參考下面的流程圖。
(01) 主線程中新建并且啟動了3個線程"t1", "t2"和"t3"。
(02) 主線程通過sleep(3000)休眠3秒。在主線程休眠3秒的過程中,我們假設"t1", "t2"和"t3"這3個線程都運行了。以"t1"為例,當它運行的時候,它會執行obj.wait()等待其它線程通過notify()或額nofityAll()來喚醒它;相同的道理,"t2"和"t3"也會等待其它線程通過nofity()或nofityAll()來喚醒它們。
(03) 主線程休眠3秒之后,接著運行。執行 obj.notifyAll() 喚醒obj上的等待線程,即喚醒"t1", "t2"和"t3"這3個線程。 緊接著,主線程的synchronized(obj)運行完畢之后,主線程釋放“obj鎖”。這樣,"t1", "t2"和"t3"就可以獲取“obj鎖”而繼續運行了!




5. 為什么notify(), wait()等函數定義在Object中,而不是Thread中
Object中的wait(), notify()等函數,和synchronized一樣,會對“對象的同步鎖”進行操作。

wait()會使“當前線程”等待,因為線程進入等待狀態,所以線程應該釋放它鎖持有的“同步鎖”,否則其它線程獲取不到該“同步鎖”而無法運行!
OK,線程調用wait()之后,會釋放它鎖持有的“同步鎖”;而且,根據前面的介紹,我們知道:等待線程可以被notify()或notifyAll()喚醒?,F在,請思考一個問題:notify()是依據什么喚醒等待線程的?或者說,wait()等待線程和notify()之間是通過什么關聯起來的?答案是:依據“對象的同步鎖”。

負責喚醒等待線程的那個線程(我們稱為“喚醒線程”),它只有在獲取“該對象的同步鎖”(這里的同步鎖必須和等待線程的同步鎖是同一個),并且調用notify()或notifyAll()方法之后,才能喚醒等待線程。雖然,等待線程被喚醒;但是,它不能立刻執行,因為喚醒線程還持有“該對象的同步鎖”。必須等到喚醒線程釋放了“對象的同步鎖”之后,等待線程才能獲取到“對象的同步鎖”進而繼續運行。

總之,notify(), wait()依賴于“同步鎖”,而“同步鎖”是對象鎖持有,并且每個對象有且僅有一個!這就是為什么notify(), wait()等函數定義在Object類,而不是Thread類中的原因。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久精品电影网| 日韩电影免费观看在线| 欧美日本亚洲视频| 日韩欧美在线播放| 国产精品电影久久久久电影网| 美女福利视频一区| 久久亚洲精品中文字幕冲田杏梨| 日韩欧美大尺度| 亚洲人成77777在线观看网| 欧美激情按摩在线| 色视频www在线播放国产成人| 97人人模人人爽人人喊中文字| 欧美猛交免费看| 国产精品99蜜臀久久不卡二区| 欧美成人精品在线视频| 这里只有精品视频在线| 青青在线视频一区二区三区| 性色av一区二区咪爱| 日韩欧美成人网| 日本精品一区二区三区在线| 亚洲石原莉奈一区二区在线观看| 日韩一区二区精品视频| 91免费视频国产| 中文字幕久久久av一区| 欧美日韩一区二区三区在线免费观看| 欧美极品少妇xxxxx| 91精品国产成人| 欧美高清在线播放| 欧美日韩xxxxx| 国产999精品久久久影片官网| 欧美一级视频在线观看| 国产精品第3页| 欧美一区二粉嫩精品国产一线天| 91久久精品美女高潮| 国产日韩欧美电影在线观看| 欧美风情在线观看| 亚洲一区亚洲二区亚洲三区| 欧美一级电影在线| 久久久久国产精品www| 亚洲免费电影一区| 亚洲自拍小视频免费观看| 欧美性视频网站| 精品视频9999| 一本大道香蕉久在线播放29| 91精品国产色综合久久不卡98| 久久精品免费播放| 国产国产精品人在线视| 北条麻妃99精品青青久久| 日韩精品在线播放| 亚洲人在线观看| 日韩免费观看在线观看| 国产精品日日摸夜夜添夜夜av| 91久久精品久久国产性色也91| 中文字幕一区二区精品| 色无极影院亚洲| 国产精欧美一区二区三区| 91精品国产一区| 欧美性猛交xxxx乱大交极品| 91高清视频在线免费观看| 日韩小视频网址| 9.1国产丝袜在线观看| 亚洲永久在线观看| 国产在线拍偷自揄拍精品| 日韩精品免费在线视频观看| 欧美最近摘花xxxx摘花| 另类美女黄大片| 日韩在线观看免费全| 日韩av第一页| 91精品国产自产在线老师啪| 国产欧美日韩丝袜精品一区| 国产精品国语对白| 欧美做受高潮电影o| 久久好看免费视频| 久久久久久久一区二区三区| 亚洲最大av网| 久久久之久亚州精品露出| 国产精品爽爽爽| 91精品久久久久久| 欧美日韩免费区域视频在线观看| 欧美激情中文字幕在线| 亚洲电影免费观看高清| 欧美综合一区第一页| 欧美中文字幕在线播放| 久久久久99精品久久久久| 国产视频亚洲精品| 亚洲成人中文字幕| 久青草国产97香蕉在线视频| 欧美黑人狂野猛交老妇| 91精品久久久久久久久久| 国产伦精品一区二区三区精品视频| 国产三级精品网站| 欧美乱大交做爰xxxⅹ性3| 国产精品视频自拍| 亚洲福利视频专区| 久久久爽爽爽美女图片| 欧洲精品毛片网站| 最新69国产成人精品视频免费| 精品久久久久久国产91| 欧美大尺度在线观看| 国产精品一区=区| 精品久久久精品| 欧美精品午夜视频| 欧美激情一区二区三区成人| 欧美日韩免费在线观看| 国产精品99久久久久久www| 亚洲精品视频免费在线观看| 久久天堂电影网| 久青草国产97香蕉在线视频| 欧美在线中文字幕| 亚洲国产精品福利| 亚洲黄页视频免费观看| 97国产精品视频人人做人人爱| 日韩av观看网址| 日韩欧美在线国产| 8x拔播拔播x8国产精品| 国产精品美女网站| 狠狠躁18三区二区一区| 国产v综合v亚洲欧美久久| 欧美亚洲激情在线| 日韩视频免费在线| 青草青草久热精品视频在线网站| 久久久国产影院| 欧美日韩成人免费| 日韩av在线播放资源| 成人激情电影一区二区| 欧美综合在线第二页| 欧美中在线观看| 中文字幕在线看视频国产欧美| 久久影院在线观看| 丝袜亚洲另类欧美重口| 亚洲色图欧美制服丝袜另类第一页| 国产日韩精品在线| 日韩中文字幕精品| 国产精品一区二区三区毛片淫片| 一本色道久久88精品综合| 亚洲网站视频福利| 亚洲精品视频在线观看视频| 成人免费视频网| 欧美精品18videos性欧美| 57pao成人国产永久免费| 国产狼人综合免费视频| 欧美高清理论片| 亚洲qvod图片区电影| 亚洲大尺度美女在线| 色青青草原桃花久久综合| 国产日韩欧美夫妻视频在线观看| 日韩av三级在线观看| 911国产网站尤物在线观看| 亚洲欧美中文日韩v在线观看| 亚洲精品720p| 亚洲男人天堂2024| 欧美乱人伦中文字幕在线| 欧美午夜激情在线| 日韩一中文字幕| 欧美激情视频在线免费观看 欧美视频免费一| 中文字幕精品在线| 国产成人综合久久| 日韩亚洲成人av在线| 成人高清视频观看www| 日韩激情av在线播放| 日韩在线欧美在线国产在线| 中文字幕日韩欧美| 欧美午夜www高清视频| 91久久精品久久国产性色也91|