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

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可能會導(dǎo)致死鎖,而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線程狀態(tài)及同步鎖的操作方法

    Java線程狀態(tài)及同步鎖的操作方法

    Java中的thread類自帶有線程的一些方法,這些方法可以讓線程睡眠,插隊,提高線程調(diào)度的優(yōu)先級等等,它們提供了改變線程狀態(tài)的操作手段,這篇文章主要介紹了Java線程狀態(tài)及同步鎖,需要的朋友可以參考下
    2021-11-11
  • javaweb servlet生成簡單驗證碼

    javaweb servlet生成簡單驗證碼

    這篇文章主要為大家詳細介紹了javaweb servlet生成簡單驗證碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • Java安全之Tomcat6 Filter內(nèi)存馬問題

    Java安全之Tomcat6 Filter內(nèi)存馬問題

    這篇文章主要介紹了Java安全之Tomcat6 Filter內(nèi)存馬,通過本文探討下Tomcat6與Tomcat8之間的區(qū)別,主要看下tomcat6和tomcat8之間createFilterChain不相同的地方 看到ApplicationFilterFactory#createFilterChain,需要的朋友可以參考下
    2022-10-10
  • Spring容器注入bean的幾種方式詳解

    Spring容器注入bean的幾種方式詳解

    這篇文章主要介紹了Spring容器注入bean的幾種方式詳解,@Configuration用來聲明一個配置類,然后使用 @Bean 注解,用于聲明一個bean,將其加入到Spring容器中,這種方式是我們最常用的一種,需要的朋友可以參考下
    2024-01-01
  • SpringBoot3.x循環(huán)依賴問題解決方案

    SpringBoot3.x循環(huán)依賴問題解決方案

    這篇文章主要介紹了SpringBoot3.x循環(huán)依賴的相關(guān)知識,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • SpringBoot中整合消息服務(wù)組件的方法

    SpringBoot中整合消息服務(wù)組件的方法

    本文介紹了消息服務(wù)組件的基本概念,以及如何在SpringBoot中整合常見的消息服務(wù)組件,如ActiveMQ、RabbitMQ和Kafka,我們探討整合消息服務(wù)組件在實際應(yīng)用場景中的優(yōu)勢,感興趣的朋友跟隨小編一起看看吧
    2023-07-07
  • intellij idea設(shè)置統(tǒng)一JavaDoc模板的方法詳解

    intellij idea設(shè)置統(tǒng)一JavaDoc模板的方法詳解

    這篇文章主要介紹了intellij idea設(shè)置統(tǒng)一JavaDoc模板的方法詳解,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • Springboot并發(fā)調(diào)優(yōu)之大事務(wù)和長連接

    Springboot并發(fā)調(diào)優(yōu)之大事務(wù)和長連接

    這篇文章主要介紹了Springboot并發(fā)調(diào)優(yōu)之大事務(wù)和長連接,重點分享長事務(wù)以及長連接導(dǎo)致的并發(fā)排查和優(yōu)化思路和示例,具有一定的參考價值,感興趣的可以了解一下
    2022-05-05
  • SpringBoot整合Ip2region獲取IP地址和定位的詳細過程

    SpringBoot整合Ip2region獲取IP地址和定位的詳細過程

    ip2region v2.0 - 是一個離線IP地址定位庫和IP定位數(shù)據(jù)管理框架,10微秒級別的查詢效率,提供了眾多主流編程語言的 xdb 數(shù)據(jù)生成和查詢客戶端實現(xiàn) ,這篇文章主要介紹了SpringBoot整合Ip2region獲取IP地址和定位,需要的朋友可以參考下
    2023-06-06
  • Java 函數(shù)式編程要點總結(jié)

    Java 函數(shù)式編程要點總結(jié)

    函數(shù)式編程并不是Java新提出的概念,其與指令編程相比,強調(diào)函數(shù)的計算比指令的計算更重要;與過程化編程相比,其中函數(shù)的計算可以隨時調(diào)用。Java8新引入函數(shù)式編程方式,大大的提高了編碼效率。本文將對涉及的對象等進行統(tǒng)一的學習及記錄。
    2021-06-06

最新評論