最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java中notify()和notifyAll()的使用區(qū)別

 更新時間:2021年06月24日 11:50:23   作者:ConstXiong  
本文主要介紹了Java中notify()和notifyAll()的使用區(qū)別,文中通過示例代碼介紹的非常詳細,感興趣的小伙伴們可以參考一下

notify() 和 notifyAll() 有什么區(qū)別?

先解釋兩個概念。

  • 等待池:假設(shè)一個線程A調(diào)用了某個對象的wait()方法,線程A就會釋放該對象的鎖后,進入到了該對象的等待池,等待池中的線程不會去競爭該對象的鎖。
  • 鎖池:只有獲取了對象的鎖,線程才能執(zhí)行對象的 synchronized 代碼,對象的鎖每次只有一個線程可以獲得,其他線程只能在鎖池中等待

然后再來說notify和notifyAll的區(qū)別

  • 如果線程調(diào)用了對象的 wait()方法,那么線程便會處于該對象的等待池中,等待池中的線程不會去競爭該對象的鎖。
  • 當有線程調(diào)用了對象的 notifyAll()方法(喚醒所有 wait 線程)或 notify()方法(只隨機喚醒一個 wait 線程),被喚醒的的線程便會進入該對象的鎖池中,鎖池中的線程會去競爭該對象鎖。也就是說,調(diào)用了notify后只要一個線程會由等待池進入鎖池,而notifyAll會將該對象等待池內(nèi)的所有線程移動到鎖池中,等待鎖競爭
  • 優(yōu)先級高的線程競爭到對象鎖的概率大,假若某線程沒有競爭到該對象鎖,它還會留在鎖池中,唯有線程再次調(diào)用 wait()方法,它才會重新回到等待池中。而競爭到對象鎖的線程則繼續(xù)往下執(zhí)行,直到執(zhí)行完了 synchronized 代碼塊,它會釋放掉該對象鎖,這時鎖池中的線程會繼續(xù)競爭該對象鎖。

綜上,所謂喚醒線程,另一種解釋可以說是將線程由等待池移動到鎖池,notifyAll調(diào)用后,會將全部線程由等待池移到鎖池,然后參與鎖的競爭,競爭成功則繼續(xù)執(zhí)行,如果不成功則留在鎖池等待鎖被釋放后再次參與競爭。而notify只會喚醒一個線程。

有了這些理論基礎(chǔ),后面的notify可能會導致死鎖,而notifyAll則不會的例子也就好解釋了

測試代碼

public class TestNotifyNotifyAll {
 
 private static Object obj = new Object();
 
 public static void main(String[] args) {
  
  //測試 RunnableImplA wait()        
  Thread t1 = new Thread(new RunnableImplA(obj));
  Thread t2 = new Thread(new RunnableImplA(obj));
  t1.start();
  t2.start();
  
  //RunnableImplB notify()
  Thread t3 = new Thread(new RunnableImplB(obj));
  t3.start();
  
  
//  //RunnableImplC notifyAll()
//  Thread t4 = new Thread(new RunnableImplC(obj));
//  t4.start();
 }
 
}
 
 
class RunnableImplA implements Runnable {
 
 private Object obj;
 
 public RunnableImplA(Object obj) {
  this.obj = obj;
 }
 
 public void run() {
  System.out.println("run on RunnableImplA");
  synchronized (obj) {
   System.out.println("obj to wait on RunnableImplA");
   try {
    obj.wait();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("obj continue to run on RunnableImplA");
  }
 }
}
 
class RunnableImplB implements Runnable {
 
 private Object obj;
 
 public RunnableImplB(Object obj) {
  this.obj = obj;
 }
 
 public void run() {
  System.out.println("run on RunnableImplB");
  System.out.println("睡眠3秒...");
  try {
   Thread.sleep(3000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  synchronized (obj) {
   System.out.println("notify obj on RunnableImplB");
   obj.notify();
  }
 }
}
 
class RunnableImplC implements Runnable {
 
 private Object obj;
 
 public RunnableImplC(Object obj) {
  this.obj = obj;
 }
 
 public void run() {
  System.out.println("run on RunnableImplC");
  System.out.println("睡眠3秒...");
  try {
   Thread.sleep(3000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  synchronized (obj) {
   System.out.println("notifyAll obj on RunnableImplC");
   obj.notifyAll();
  }
 }
}

結(jié)果:僅調(diào)用一次 obj.notify(),線程 t1 或 t2 中的一個始終在等待被喚醒,程序不終止

run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplB
睡眠3秒...
notify obj on RunnableImplB
obj continue to run on RunnableImplA

把 t3 注掉,啟動 t4 線程。調(diào)用 obj.notifyAll() 方法

public class TestNotifyNotifyAll { 
 private static Object obj = new Object();
  public static void main(String[] args) {
  
  //測試 RunnableImplA wait()        
  Thread t1 = new Thread(new RunnableImplA(obj));
  Thread t2 = new Thread(new RunnableImplA(obj));
  t1.start();
  t2.start();
  
//  //RunnableImplB notify()
//  Thread t3 = new Thread(new RunnableImplB(obj));
//  t3.start();
  
  
  //RunnableImplC notifyAll()
  Thread t4 = new Thread(new RunnableImplC(obj));
  t4.start();
 } 
}

結(jié)果:t1、t2線程均可以執(zhí)行完畢

run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplA
obj to wait on RunnableImplA
run on RunnableImplC
睡眠3秒...
notifyAll obj on RunnableImplC
obj continue to run on RunnableImplA
obj continue to run on RunnableImplA

到此這篇關(guān)于Java中notify()和notifyAll()的使用區(qū)別的文章就介紹到這了,更多相關(guān)Java notify()和notifyAll()內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實現(xiàn)圖片裁切的工具類實例

    java實現(xiàn)圖片裁切的工具類實例

    這篇文章主要介紹了java實現(xiàn)圖片裁切的工具類實例,涉及Java針對圖片的讀取、修改等相關(guān)操作技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • Java深入探索單例模式的應用

    Java深入探索單例模式的應用

    單例模式(Singleton Pattern)是 Java 中最簡單的設(shè)計模式之一。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式
    2022-06-06
  • Java代碼里如何拼接SQL語句到mybatis的xml

    Java代碼里如何拼接SQL語句到mybatis的xml

    這篇文章主要介紹了Java代碼里拼接SQL語句到mybatis的xml操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Jenkins如何實現(xiàn)自動打包部署linux

    Jenkins如何實現(xiàn)自動打包部署linux

    這篇文章主要介紹了Jenkins如何實現(xiàn)自動打包部署linux,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • java編程實現(xiàn)郵件定時發(fā)送的方法

    java編程實現(xiàn)郵件定時發(fā)送的方法

    這篇文章主要介紹了java編程實現(xiàn)郵件定時發(fā)送的方法,涉及Java基于定時器實現(xiàn)計劃任務(wù)的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-11-11
  • httpclient提交json參數(shù)的示例詳解

    httpclient提交json參數(shù)的示例詳解

    httpclient使用post提交json參數(shù),和使用表單提交區(qū)分,本文結(jié)合示例代碼講解的非常詳細,補充介紹了HttpClient請求傳json參數(shù)的案例代碼,感興趣的朋友一起看看吧
    2024-02-02
  • Java中的動態(tài)和靜態(tài)編譯實例詳解

    Java中的動態(tài)和靜態(tài)編譯實例詳解

    這篇文章主要介紹了Java中的動態(tài)和靜態(tài)編譯實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • java中concat()方法的使用說明

    java中concat()方法的使用說明

    這篇文章主要介紹了java中concat()方法的使用說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • java判斷域名無法訪問自行訪問下一條

    java判斷域名無法訪問自行訪問下一條

    這篇文章主要為大家介紹了java實現(xiàn)判斷域名無法訪問的時候自行訪問下一條域名示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • Java使用正則表達式匹配獲取鏈接地址的方法示例

    Java使用正則表達式匹配獲取鏈接地址的方法示例

    這篇文章主要介紹了Java使用正則表達式匹配獲取鏈接地址的方法,簡單分析了java正則匹配常用方法及獲取網(wǎng)址鏈接的相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08

最新評論

临安市| 灵台县| 双桥区| 车致| 金湖县| 永福县| 南部县| 芒康县| 东阿县| 土默特左旗| 德昌县| 富裕县| 深水埗区| 陈巴尔虎旗| 永平县| 无棣县| 南皮县| 司法| 永仁县| 新建县| 沿河| 兴安县| 平山县| 茌平县| 水富县| 微山县| 兴仁县| 信丰县| 渝中区| 安国市| 长海县| 宿松县| 和平区| 荆门市| 利川市| 黑水县| 平乐县| 望城县| 西峡县| 瑞昌市| 保亭|