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

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

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

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

先解釋兩個(gè)概念。

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

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

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

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

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

測試代碼

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 中的一個(gè)始終在等待被喚醒,程序不終止

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 注掉,啟動(dòng) 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類自帶有線程的一些方法,這些方法可以讓線程睡眠,插隊(duì),提高線程調(diào)度的優(yōu)先級(jí)等等,它們提供了改變線程狀態(tài)的操作手段,這篇文章主要介紹了Java線程狀態(tài)及同步鎖,需要的朋友可以參考下
    2021-11-11
  • javaweb servlet生成簡單驗(yàn)證碼

    javaweb servlet生成簡單驗(yàn)證碼

    這篇文章主要為大家詳細(xì)介紹了javaweb servlet生成簡單驗(yàn)證碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    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用來聲明一個(gè)配置類,然后使用 @Bean 注解,用于聲明一個(gè)bean,將其加入到Spring容器中,這種方式是我們最常用的一種,需要的朋友可以參考下
    2024-01-01
  • SpringBoot3.x循環(huán)依賴問題解決方案

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

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

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

    本文介紹了消息服務(wù)組件的基本概念,以及如何在SpringBoot中整合常見的消息服務(wù)組件,如ActiveMQ、RabbitMQ和Kafka,我們探討整合消息服務(wù)組件在實(shí)際應(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模板的方法詳解,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Springboot并發(fā)調(diào)優(yōu)之大事務(wù)和長連接

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

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

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

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

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

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

最新評論