欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java wait和notify虛假喚醒原理

 更新時間:2020年04月16日 09:47:18   作者:經(jīng)典雞翅  
這篇文章主要介紹了Java wait和notify虛假喚醒,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

自己在此記錄一下,方便日后復習。

虛假喚醒的概念

jdk官方文檔解釋:

所以說在wait和notify一塊使用時,如果使用if作為條件時,會有虛假喚醒的情況發(fā)生,所以必須使用while作為循環(huán)條件。下面來舉例實驗:

首先,創(chuàng)建一個資源類:(在多線程中,一般都是資源類和線程操作解耦,不放在用同一個類中,只有在線程操作資源類時,才會創(chuàng)建資源類的對象)

package com.test;

/**
 * 資源類
 * @author Huxudong
 * @createTime 2020-04-01 21:57:39
 **/
public class Resource {
  /** 產(chǎn)品數(shù) */
  private int product = 0;

  /** 進貨 */
  public synchronized void get() {
    if(product >= 10) {
      System.out.println(Thread.currentThread().getName()+":"+"產(chǎn)品已滿!");
      /** 當商品已經(jīng)滿的時候,進貨線程掛起 */
      try {
        this.wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    /** 進貨 */
    System.out.println(Thread.currentThread().getName()+":"+ ++product);
    /** 喚醒其他線程 */
    this.notifyAll();
    
  }

  /** 售貨 */
  public synchronized void sale() {
    if(product <= 0) {
      System.out.println(Thread.currentThread().getName()+":"+"產(chǎn)品已空");
      try {
        this.wait();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    /** 售貨 */
    System.out.println(Thread.currentThread().getName()+":"+ --product);
    /** 喚醒其他線程 */
    this.notify();
  }
}

然后再創(chuàng)建線程來操作我們的資源類(通過java8新特性Lambda表達式直接創(chuàng)建)

package com.test;

import java.util.concurrent.TimeUnit;

/**
 * 線程操作資源類,實現(xiàn)線程與資源類的解耦合
 * @author Huxudong
 * @createTime 2020-04-01 23:13:54
 **/
public class TestPc {
  public static void main(String[] args) {
    Resource resource = new Resource();
    new Thread(()->{
      for (int i = 0; i < 20; i++) {
        try {
          /** 睡眠,便于觀察結(jié)果 */
          TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        resource.get();
      }
    },"生產(chǎn)者A").start();



    new Thread(()->{
      for (int i = 0; i < 20; i++) {
        resource.sale();
      }

    },"消費者C").start();

    new Thread(()->{
      for (int i = 0; i < 20; i++) {

        resource.get();
      }

    },"生產(chǎn)者B").start();

    new Thread(()->{
      for (int i = 0; i < 20; i++) {
        resource.sale();
      }

    },"消費者D").start();
  }
}

先來看看如果使用if條件會發(fā)生什么:

對,你沒看錯,怎么可能會出現(xiàn)負數(shù)呢,這肯定是不對的。冷靜下來分析一下,還是有點頭緒,知道哪里出現(xiàn)了問題的(那你是一個處事不驚的人,很厲害)。

來,分析一下,一開始先調(diào)用了消費者C,D線程(因為我們寫了睡眠在生產(chǎn)者中),消費者此時發(fā)現(xiàn)此時product資源為0,所以,消費者C,D這兩個兄弟,沒辦法只能調(diào)用wait方法,睡眠了,并且釋放了鎖。

但是此時第一個消費者已經(jīng)蘇醒了,發(fā)動機開始生產(chǎn)產(chǎn)品了,并且生產(chǎn)之后,又喚醒了所有等待的消費者線程。這消費者C,D兩兄弟終于蘇醒了,D哥們先獲得了鎖,所以就先消費了一個產(chǎn)品,然后就又發(fā)現(xiàn)沒有產(chǎn)品了,又傷心的休眠去了,但是不要忘了,此時還有一個C哥們被喚醒了啊,你喚醒了人家,人家總的干點什么事情吧,不然這多難受,剛好不巧的是,此時的判斷條件是if,所以此時C哥們便不受條件的約束,接著上面自己睡眠的代碼處執(zhí)行,毅然決然的又去消費了一個產(chǎn)品,原來D哥們消費后,就已經(jīng)為0了,這個C哥們再去消費減一,不就是-1了嗎,以此類推分析。發(fā)現(xiàn)如果判斷條件用不好,此時喚醒的C哥們就相當于虛假喚醒的了,會給程序帶來不可預估的錯誤。所以在這里判斷必須要使用while,先來看看把if換成while的結(jié)果。

這回結(jié)果就比較正常了,為什么使用while就可以呢,因為像上文所說,即使喚醒了所有的消費者線程,此時會不停while循環(huán)判斷,如果此時條件是為0,那么C哥們就不能出while,那么他也就不回執(zhí)行下面消費產(chǎn)品的減減操作了,那么就會避免了這種錯誤。這也是官方提倡的在使用wait 和notifyAll的時候,必須使用while循環(huán)條件判斷。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java觀察者模式之實現(xiàn)對象間的一對多依賴

    Java觀察者模式之實現(xiàn)對象間的一對多依賴

    這篇文章主要介紹了Java觀察者模式之實現(xiàn)對象間的一對多依賴的方法,Java觀察者模式是一種行為型設計模式,用于實現(xiàn)對象之間的消息傳遞和通信,文中有詳細的實現(xiàn)步驟和代碼示例,,需要的朋友可以參考下
    2023-05-05
  • springboot網(wǎng)站應用使用第三方qq登錄的實現(xiàn)過程

    springboot網(wǎng)站應用使用第三方qq登錄的實現(xiàn)過程

    這篇文章主要介紹了springboot網(wǎng)站應用使用第三方qq登錄,本文通過實例圖文相結(jié)合給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • java實現(xiàn)發(fā)送短信驗證碼

    java實現(xiàn)發(fā)送短信驗證碼

    這篇文章主要為大家詳細介紹了java實現(xiàn)發(fā)送短信驗證碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07
  • java獲取ip地址示例

    java獲取ip地址示例

    在JSP里,獲取客戶端的IP地址的方法是:request.getRemoteAddr(),這種方法在大部分情況下都是有效的。但是在通過了Apache,Squid等反向代理軟件就不能獲取到客戶端的真實IP地址了
    2014-04-04
  • 詳解elasticsearch之metric聚合實現(xiàn)示例

    詳解elasticsearch之metric聚合實現(xiàn)示例

    這篇文章主要為大家介紹了elasticsearch之metric聚合實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-01-01
  • SpringBoot在線代碼修改器的問題及解決方法

    SpringBoot在線代碼修改器的問題及解決方法

    這篇文章主要介紹了SpringBoot在線代碼修改器的問題及解決方法,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • 詳解java平臺解析協(xié)議相關(guān)備忘

    詳解java平臺解析協(xié)議相關(guān)備忘

    這篇文章主要介紹了詳解java平臺解析協(xié)議相關(guān)備忘,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-01-01
  • SpringBoot整合ActiveMQ的詳細步驟

    SpringBoot整合ActiveMQ的詳細步驟

    昨天仔細研究了activeMQ消息隊列,也遇到了些坑,下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合ActiveMQ的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-11-11
  • SpringBoot中SmartLifecycle的使用解析

    SpringBoot中SmartLifecycle的使用解析

    這篇文章主要介紹了SpringBoot中SmartLifecycle的使用解析,SmartLifecycle是一個擴展了Lifecycle接口,可以跟蹤spring容器ApplicationContext刷新或者關(guān)閉的接口,實現(xiàn)該接口的實現(xiàn)類有特定的執(zhí)行順序,需要的朋友可以參考下
    2023-11-11
  • 關(guān)于服務網(wǎng)關(guān)Spring Cloud Zuul(Finchley版本)

    關(guān)于服務網(wǎng)關(guān)Spring Cloud Zuul(Finchley版本)

    這篇文章主要介紹了關(guān)于服務網(wǎng)關(guān)Spring Cloud Zuul(Finchley版本),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03

最新評論