成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java中wait、notify、notifyAll使用詳解

rozbo / 2729人閱讀

摘要:用法中規(guī)定,在調(diào)用者三個(gè)方法時(shí),當(dāng)前線程必須獲得對(duì)象鎖。作用方法作用線程自動(dòng)釋放占有的對(duì)象鎖,并等待。當(dāng)生產(chǎn)者生產(chǎn)了一個(gè)數(shù)據(jù)或者消費(fèi)者消費(fèi)了一個(gè)數(shù)據(jù)之后,使用方法來(lái)通知所有等待當(dāng)前對(duì)象鎖的線程,但是一次只會(huì)有一個(gè)等待的線程能拿到鎖。

基礎(chǔ)知識(shí)

首先我們需要知道,這幾個(gè)都是Object對(duì)象的方法。換言之,Java中所有的對(duì)象都有這些方法。

public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait() throws InterruptedException {
    wait(0);
}

其中notify()、notifyAll()、wait(long timeout)是本地方法
其次我們需要知道這幾個(gè)方法主要是用來(lái)個(gè)線程之間通信的。那可能就有人會(huì)問(wèn),既然是用來(lái)線程之間通信的,那為什么這幾個(gè)方法不是在線程類Thread上呢?對(duì)于這個(gè)問(wèn)題,我們先來(lái)看下這幾個(gè)方法的具體使用方式再來(lái)回答這個(gè)問(wèn)題。

用法

Java中規(guī)定,在調(diào)用者三個(gè)方法時(shí),當(dāng)前線程必須獲得對(duì)象鎖。因此就得配合synchronized關(guān)鍵字來(lái)使用

//使用模式,不代表可運(yùn)行代碼
synchronized(object) {
    while(contidion) {
        object.wait();
    }
    //object.notify();
    //object.notifyAll();
}

或者

public synchronized void methodName() {
    while(contidion) {
        object.wait();
    }
    //object.notify();
    //object.notifyAll();
}

在synchronized拿到對(duì)象鎖之后,synchronized代碼塊或者方法中,必定是會(huì)持有對(duì)象鎖的,因此就可以使用wait()或者notify()。
通過(guò)上述使用方法,我們也能很好理解為什么這幾個(gè)方法是在Object上而不是在Thread上。因?yàn)槊總€(gè)對(duì)象都可以作為synchronized鎖的對(duì)象,因此wait、notify等必須和對(duì)象關(guān)聯(lián)才能配合synchronized使用。

作用
方法 作用
wait 線程自動(dòng)釋放占有的對(duì)象鎖,并等待notify。
notify 隨機(jī)喚醒一個(gè)正在wait當(dāng)前對(duì)象的線程,并讓被喚醒的線程拿到對(duì)象鎖
notifyAll 喚醒所有正在wait當(dāng)前對(duì)象的線程,但是被喚醒的線程會(huì)再次去競(jìng)爭(zhēng)對(duì)象鎖。因?yàn)橐淮沃挥幸粋€(gè)線程能拿到鎖,所有其他沒(méi)有拿到鎖的線程會(huì)被阻塞。推薦使用。
實(shí)際案例

接下來(lái)我們就使用wait()、notify()來(lái)實(shí)現(xiàn)一個(gè)生產(chǎn)者、消費(fèi)者模式。這個(gè)也是面試過(guò)程中可能會(huì)被問(wèn)到的地方。至于什么是生產(chǎn)者消費(fèi)者模式,不明白的同學(xué)請(qǐng)自行百度。
首先是一些基礎(chǔ)的代碼

private static Boolean run = true;//控制是否生產(chǎn)和消費(fèi)
private static final Integer MAX_CAPACITY = 5;//緩沖區(qū)最大數(shù)量
private static final LinkedBlockingQueue queue = new LinkedBlockingQueue<>();//緩沖隊(duì)列

生產(chǎn)者代碼

/**
 * 生產(chǎn)者
 */
class Producter extends Thread {
    @Override
    public void run() {
        while (run) {
            synchronized (queue) {
                while (queue.size() >= MAX_CAPACITY * 2) {
                    try {
                        System.out.println("緩沖隊(duì)列已滿,等待消費(fèi)");
                        queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                try {
                    String string = UUID.randomUUID().toString();
                    queue.put(string);
                    System.out.println("生產(chǎn):" + string);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                queue.notifyAll();//通知生產(chǎn)者和消費(fèi)者
            }
        }
    }
}

消費(fèi)者代碼

/**
 * 消費(fèi)者
 */
class Consumer extends Thread {
    @Override
    public void run() {
        while (run) {
            synchronized (queue) {
                while (queue.isEmpty()) {
                    try {
                        System.out.println("隊(duì)列為空,等待生產(chǎn)");
                        queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                try {
                    System.out.println("消費(fèi):" + queue.take());
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                queue.notifyAll();//通知生產(chǎn)者和消費(fèi)者
            }
        }
    }
}

代碼說(shuō)明

1、生產(chǎn)者和消費(fèi)者都繼承了線程Thread,因?yàn)閣ait、notify本身就是線程間通信使用
2、生產(chǎn)者和消費(fèi)者都有兩層while,外層的while是用來(lái)判斷是否運(yùn)行生產(chǎn)者和消費(fèi)者。內(nèi)存的while用來(lái)判斷隊(duì)列queue是否已滿或者為空,如果滿足條件,則使得當(dāng)前線程變成等待狀態(tài)(等待notify)。
3、內(nèi)層的條件判斷為什么用while不用if,原因是當(dāng)線程被wait之后,會(huì)釋放對(duì)象鎖。當(dāng)?shù)却木€程被notify之后,必須再次嘗試去獲取對(duì)象鎖,如果沒(méi)有獲取到對(duì)象鎖,那還必須等待,直到拿到對(duì)象鎖之后才能向后執(zhí)行。
4、當(dāng)生產(chǎn)者生產(chǎn)了一個(gè)數(shù)據(jù)或者消費(fèi)者消費(fèi)了一個(gè)數(shù)據(jù)之后,使用notifyAll()方法來(lái)通知所有等待當(dāng)前對(duì)象鎖的線程,但是一次只會(huì)有一個(gè)等待的線程能拿到鎖。
5、我們使用queue作為鎖的對(duì)象在不同線程之間進(jìn)行通信

代碼運(yùn)行結(jié)果

隊(duì)列為空,等待生產(chǎn)
生產(chǎn):e422484e-8eb3-4a91-8a7c-97e21d7ef498
生產(chǎn):7894b802-2529-4798-ba98-9f0657f39240
生產(chǎn):848f6759-a427-4a94-89dc-3f484daaa467
生產(chǎn):f711d3dc-972c-4c44-8640-faffe376d354
生產(chǎn):38a08e62-d774-4ed5-8b51-f1ad534c246f
消費(fèi):e422484e-8eb3-4a91-8a7c-97e21d7ef498
消費(fèi):7894b802-2529-4798-ba98-9f0657f39240
消費(fèi):848f6759-a427-4a94-89dc-3f484daaa467
消費(fèi):f711d3dc-972c-4c44-8640-faffe376d354
消費(fèi):38a08e62-d774-4ed5-8b51-f1ad534c246f
隊(duì)列為空,等待生產(chǎn)
生產(chǎn):9fae26f3-0b6e-4fbd-9620-040667efe0af
生產(chǎn):95bb1d88-e08a-4f70-a270-f75760994184
消費(fèi):9fae26f3-0b6e-4fbd-9620-040667efe0af
消費(fèi):95bb1d88-e08a-4f70-a270-f75760994184
隊(duì)列為空,等待生產(chǎn)
生產(chǎn):13d304bc-dff3-44a4-9527-2e0facd884e7
生產(chǎn):2693e069-bae1-4beb-adcd-a3c3bf5d232b
消費(fèi):13d304bc-dff3-44a4-9527-2e0facd884e7
消費(fèi):2693e069-bae1-4beb-adcd-a3c3bf5d232b

由結(jié)果也可以看出來(lái),生產(chǎn)和消費(fèi)是無(wú)規(guī)則的,因?yàn)殡m然notifyAll()通知了所有的等待線程,但是不確定那個(gè)線程中能拿到對(duì)象鎖。但是也有一個(gè)很明顯的問(wèn)題,因?yàn)橥瑫r(shí)只有一個(gè)線程能拿到對(duì)象鎖,生產(chǎn)者和消費(fèi)者不可能同時(shí)運(yùn)行。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/74455.html

相關(guān)文章

  • Java 基礎(chǔ) | Object 源碼解析

    摘要:注釋指出方法返回散列值。直到其他線程調(diào)用此對(duì)象的方法或方法,當(dāng)前線程被喚醒進(jìn)入就緒狀態(tài)??偝瑫r(shí)時(shí)間以納秒為單位計(jì)算為。以上注釋主要就是描述了,和方法的使用規(guī)范。主要的區(qū)別在于在釋放同時(shí),釋放了對(duì)象鎖的控制。 showImg(https://segmentfault.com/img/remote/1460000020031663?w=1240&h=734); Java 是一門面向?qū)ο蟮恼Z(yǔ)...

    dendoink 評(píng)論0 收藏0
  • Javawait/notify/notifyAll

    摘要:等待一段時(shí)間是否有線程喚醒鎖,如果沒(méi)有,超時(shí)自動(dòng)喚醒。隨機(jī)喚醒等待隊(duì)列中的等待同一個(gè)鎖的一個(gè)線程,使這個(gè)線程退出等待隊(duì)列,進(jìn)入可運(yùn)行狀態(tài)。條件隊(duì)列中是處于等待狀態(tài)的線程,等待特定條件為真。在一般情況下,總應(yīng)該調(diào)用喚醒所有需要被喚醒的線程。 方法 java.lang.Object public final native void wait() throws InterruptedExce...

    terasum 評(píng)論0 收藏0
  • Java 多線程核心技術(shù)梳理(附源碼)

    摘要:本文對(duì)多線程基礎(chǔ)知識(shí)進(jìn)行梳理,主要包括多線程的基本使用,對(duì)象及變量的并發(fā)訪問(wèn),線程間通信,的使用,定時(shí)器,單例模式,以及線程狀態(tài)與線程組。源碼采用構(gòu)建,多線程這部分源碼位于模塊中。通知可能等待該對(duì)象的對(duì)象鎖的其他線程。 本文對(duì)多線程基礎(chǔ)知識(shí)進(jìn)行梳理,主要包括多線程的基本使用,對(duì)象及變量的并發(fā)訪問(wèn),線程間通信,lock的使用,定時(shí)器,單例模式,以及線程狀態(tài)與線程組。 寫在前面 花了一周時(shí)...

    Winer 評(píng)論0 收藏0
  • java多線程(7)wait()、notify()和notityALL()

    摘要:已經(jīng)在上面有提到過(guò),和的作用是喚醒正在的線程,是隨機(jī)喚醒線程中的一個(gè),則是喚醒全部。釋放和不釋放鎖在多線程的操作中,鎖的釋放與否是必須要清楚的,是會(huì)釋放鎖,而則不會(huì)。 wait wait方法是Object中的方法,這個(gè)方法的功能特性:1).執(zhí)行wait方法的前提是當(dāng)前線程已經(jīng)獲取到對(duì)象的鎖,也就是wait方法必須在synchronized修飾的代碼塊或者方法中使用。2).執(zhí)行wait之...

    LiuRhoRamen 評(píng)論0 收藏0
  • java并發(fā)編程學(xué)習(xí)之線程的生命周期-wait,notify,notifyall(六)

    摘要:不釋放持有的鎖,釋放鎖。在調(diào)用方法前,必須持有鎖,調(diào)用喚醒,也要持有鎖。休眠一定時(shí)間后,進(jìn)入就緒狀態(tài)。這兩個(gè)都能被方法中斷當(dāng)前狀態(tài)。用法方獲取鎖判斷條件,不滿足繼續(xù)滿足執(zhí)行其他業(yè)務(wù)方獲取鎖改變條件通知為什么是而不是會(huì)一直循環(huán),直到條件滿足。 sleep和wait sleep是Thread類的方法,wait是Object的方法。 sleep可以到處使用,wait必須是在同步方法或者代碼...

    Terry_Tai 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<