成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java并發編程之二徹底理解Java的wait和Notify機制

開發 后端
wait方法的作用是使當前執行代碼的線程進行等待,它是Object類的方法,該方法用來將當前線程置入等待隊列中,并且在wait所在的代碼行處停止執行,直到接到通知或被中斷為止。

 [[410508]]

簡單介紹

  • wait方法

wait方法的作用是使當前執行代碼的線程進行等待,它是Object類的方法,該方法用來將當前線程置入等待隊列中,并且在wait所在的代碼行處停止執行,直到接到通知或被中斷為止。

該方法只能在同步方法或同步塊中調用(即需要先獲得對象的監視器鎖,一般來說在 synchronized 代碼塊或者synchronized修飾的方法中使用),否則拋出異常

IllegalMonitorStateException。

在A線程中調用Lock對象的wait方法以后,會釋放Lock對象的監視器鎖,同時將A線程放置于Lock對象的等待隊列,A線程進入WAITING狀態(Thread狀態查看系列一)。

  • notify/notifyAll方法

notify/notifyAll方法的作用是喚醒執行對象的等待列表中的一個/所有線程,將其喚醒繼續工作。

同樣的,notify/notifyAll方法也只能在同步方法或同步塊中調用,即在調用前,線程也必須獲得該對象的監視器鎖。

在B線程中調用Lock對象的notify/notifyAll方法以后,Lock對象等待隊列中的A線程從WAITING狀態進入BLOCKED狀態,而不是直接進入RUNNABLE狀態。只有等B線程釋放了Lock對象的監視器鎖,并且A線程拿到以后,才進入到RUNNABLE狀態。所以在編程中,盡量在使用了notify/notifyAll() 后立即釋放對象的監視器鎖,以便讓其他線程獲得鎖進入RUNNABLE狀態。

  • 其他注意事項

wait、notify/notifyAll 方法是Object的本地final方法,無法被重寫。

notify 和wait 的順序不能錯,如果A線程先執行notify方法,B線程再執行wait方法,那么B線程是無法被喚醒的。

實例詳解

  1. public class WaitThread extends Thread { 
  2.  
  3.     private Object lock; 
  4.  
  5.     public WaitThread(Object lock) { 
  6.         this.lock = lock; 
  7.     } 
  8.  
  9.     @Override 
  10.     public void run() { 
  11.         synchronized (lock) { 
  12.             System.out.println("WaitThread開始執行run方法"); 
  13.             try { 
  14.                 System.out.println("WaitThread開始執行wait方法"); 
  15.                 lock.wait(); 
  16.                 System.out.println("WaitThread被喚醒"); 
  17.             } catch (InterruptedException e) { 
  18.                 e.printStackTrace(); 
  19.             } 
  20.         } 
  21.     } 
  1. public class NotifyThread extends Thread { 
  2.  
  3.     private Object lock; 
  4.  
  5.     public NotifyThread(Object lock) { 
  6.         this.lock = lock; 
  7.     } 
  8.  
  9.     @Override 
  10.     public void run() { 
  11.         System.out.println("NotifyThread開始執行run方法"); 
  12.         try { 
  13.             System.out.println("NotifyThread睡眠2秒"); 
  14.             Thread.sleep(2000); 
  15.         } catch (InterruptedException e) { 
  16.             e.printStackTrace(); 
  17.         } 
  18.         synchronized (lock) { 
  19.             System.out.println("NotifyThread開始執行notify方法"); 
  20.             lock.notify(); 
  21.             try { 
  22.                 System.out.println("NotifyThread執行notify方法后繼續睡眠2秒"); 
  23.                 Thread.sleep(2000); 
  24.             } catch (InterruptedException e) { 
  25.                 e.printStackTrace(); 
  26.             } 
  27.             System.out.println("NotifyThread睡眠2秒結束,并釋放對象監視器鎖"); 
  28.         } 
  29.     } 
  1. public class Main { 
  2.     public static void main(String[] args) { 
  3.  
  4.         Object lock = new Object(); 
  5.  
  6.         // 創建2個線程 
  7.         WaitThread waitThread = new WaitThread(lock); 
  8.         NotifyThread notifyThread = new NotifyThread(lock); 
  9.         // 啟動他們 
  10.         waitThread.start(); 
  11.         notifyThread.start(); 
  12.     } 
  1. NotifyThread開始執行run方法 
  2. WaitThread開始執行run方法 
  3. WaitThread開始執行wait方法 
  4. NotifyThread睡眠2秒 
  5. NotifyThread開始執行notify方法 
  6. NotifyThread執行notify方法后繼續睡眠2秒 
  7. NotifyThread睡眠2秒結束,并釋放對象監視器鎖 
  8. WaitThread被喚醒 

WaitThread在拿到lock的監視器鎖以后調用wait方法。

NotifyThread在啟動以后先睡眠2秒,保證了notify方法在wait方法后面。

NotifyThread執行notify方法后繼續睡眠2秒,這個時候NotifyThread并沒有釋放Lock的監視器鎖,因此WaitThread處于BLOCKED狀態并沒有被真正被喚醒。

NotifyThread睡眠2秒結束,并釋放對象監視器鎖,這個時候NotifyThread取到Lock的監視器鎖并進入到RUNNABLE狀態。

進階思考

如果A線程獲得了多個對象的監視器鎖,然后調用其中1個對象的wait方法,是釋放所有對象的鎖還是只釋放調用的那個對象的鎖呢?

我們一起通過一個示例來進行一下測試。

  1. public class WaitThread extends Thread { 
  2.  
  3.     private Object lock; 
  4.     private Object other; 
  5.  
  6.     public WaitThread(Object lock, Object other) { 
  7.         this.lock = lock; 
  8.         this.other = other; 
  9.     } 
  10.  
  11.     @Override 
  12.     public void run() { 
  13.         synchronized (lock) { 
  14.             synchronized (other) { 
  15.                 System.out.println("WaitThread開始執行run方法"); 
  16.                 try { 
  17.                     System.out.println("WaitThread開始執行wait方法"); 
  18.                     lock.wait(); 
  19.                     System.out.println("WaitThread被喚醒"); 
  20.                 } catch (InterruptedException e) { 
  21.                     e.printStackTrace(); 
  22.                 } 
  23.             } 
  24.         } 
  25.     } 
  1. public class NotifyThread extends Thread { 
  2.  
  3.     private Object lock; 
  4.     private Object other; 
  5.  
  6.     public NotifyThread(Object lock, Object other) { 
  7.         this.lock = lock; 
  8.         this.other = other; 
  9.     } 
  10.  
  11.     @Override 
  12.     public void run() { 
  13.         System.out.println("NotifyThread開始執行run方法"); 
  14.         try { 
  15.             System.out.println("NotifyThread睡眠2秒"); 
  16.             Thread.sleep(2000); 
  17.         } catch (InterruptedException e) { 
  18.             e.printStackTrace(); 
  19.         } 
  20.         synchronized (lock) { 
  21.             System.out.println("NotifyThread獲得lock鎖"); 
  22.  
  23.             synchronized (other) { 
  24.                 System.out.println("NotifyThread獲得other鎖"); 
  25.                 System.out.println("NotifyThread開始執行notify方法"); 
  26.                 lock.notify(); 
  27.                 try { 
  28.                     System.out.println("NotifyThread執行notify方法后繼續睡眠2秒"); 
  29.                     Thread.sleep(2000); 
  30.                 } catch (InterruptedException e) { 
  31.                     e.printStackTrace(); 
  32.                 } 
  33.                 System.out.println("NotifyThread睡眠2秒結束,并釋放對象監視器鎖"); 
  34.             } 
  35.         } 
  36.     } 
  1. public class Main { 
  2.     public static void main(String[] args) { 
  3.  
  4.         Object lock = new Object(); 
  5.         Object other = new Object(); 
  6.  
  7.         // 創建2個線程 
  8.         WaitThread waitThread = new WaitThread(lock, other); 
  9.         NotifyThread notifyThread = new NotifyThread(lock, other); 
  10.         // 啟動他們 
  11.         waitThread.start(); 
  12.         notifyThread.start(); 
  13.     } 
  1. WaitThread開始執行run方法 
  2. WaitThread開始執行wait方法 
  3. NotifyThread開始執行run方法 
  4. NotifyThread睡眠2秒 
  5. NotifyThread獲得lock鎖 

WaitThread線程拿到lock和other的對象鎖以后,執行了lock的wait方法。NotifyThread線程在睡眠2秒后,僅拿到了lock鎖,說明wait方法只釋放了被執行對應的鎖,這樣就造成了死鎖。

因此如果使用wait和notify機制時,一定要確認Wait線程和Notify線程獲取對象鎖的情況,盡量避免在獲取多個對象鎖的情況下使用,防止造成死鎖問題。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2025-01-09 08:49:36

Java并發編程

2010-03-15 18:25:27

Java編程語言

2023-10-08 09:34:11

Java編程

2020-07-06 08:03:32

Java悲觀鎖樂觀鎖

2017-09-19 14:53:37

Java并發編程并發代碼設計

2020-12-11 07:32:45

編程ThreadLocalJava

2020-11-13 08:42:24

Synchronize

2025-01-10 07:10:00

2025-03-26 00:55:00

2015-08-05 09:33:21

Javawaitnotify

2012-03-09 10:44:11

Java

2020-12-08 08:53:53

編程ThreadPoolE線程池

2019-11-07 09:20:29

Java線程操作系統

2021-03-10 15:59:39

JavaSynchronize并發編程

2024-06-21 08:32:24

2024-12-31 09:00:12

Java線程狀態

2021-10-11 11:58:41

Channel原理recvq

2020-12-15 08:06:45

waitnotifyCondition

2024-05-17 10:05:06

Java機制應用

2024-03-15 08:23:26

異步編程函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 99热欧美 | 国产日韩欧美在线 | 人人九九 | 色精品| 91中文在线观看 | 一区二区三区在线观看免费视频 | 亚洲视频免费在线观看 | 国产一区二 | 欧美激情黄色 | 日本成人中文字幕 | 成人网址在线观看 | 色婷婷久久久亚洲一区二区三区 | 国产福利在线播放 | 亚洲精品电影网在线观看 | 亚洲午夜久久久 | 免费在线看黄 | 成人av观看 | 国产91在线 | 亚洲 | 久久精品国产一区二区电影 | 久久国产精品久久久久久 | 亚洲视频在线观看一区二区三区 | 久久久久久免费精品一区二区三区 | 国产乱码精品一品二品 | 色综合天天天天做夜夜夜夜做 | 狠狠av| 亚洲成人自拍 | 特黄级国产片 | 国产成人精品免费 | 福利片在线观看 | 亚洲成人日韩 | 久久久久一区二区三区四区 | 一区欧美 | 爱爱无遮挡 | 在线三级网址 | 精品在线一区 | 欧美电影一区 | 久久久久久中文字幕 | 韩日av在线 | 久久99这里只有精品 | 亚洲国产成人精品女人久久久 | 日韩欧美一区二区三区四区 |