Java EE初階——wait 和 notify

?1.?線程饑餓

線程饑餓是指一個或多個線程因長期無法獲取所需資源(如鎖,CPU時間等)而持續處于等待狀態,導致其任務無法推進的現象。

典型場景

  1. 優先級搶占

    • 在支持線程優先級的系統中,高優先級線程可能持續搶占CPU資源

    • 導致低優先級線程長期無法獲得CPU時間片

  2. 不公平鎖競爭

    • 某些線程頻繁獲取鎖,其他線程長期等待

    • 典型場景:某個線程釋放鎖后立即重新競爭并獲得鎖

    • 導致其他線程始終處于BLOCKED狀態而無法執行

  3. 資源分配不均

    • 某些線程占用大量I/O或內存資源

    • 其他線程因資源不足而無法執行

  4. 線程池配置不當

    • 固定大小線程池中,長任務占用所有線程

    • 短任務無法得到執行機會

關鍵問題點

  1. 鎖獲取模式問題

    • 活躍線程釋放鎖后立即重新請求鎖

    • 處于RUNNABLE狀態的線程比BLOCKED狀態的線程有更快的響應速度

    • 操作系統喚醒BLOCKED線程需要上下文切換,造成競爭劣勢

  2. 系統調度機制

    • 默認調度策略可能不利于公平性

    • 缺乏有效的防饑餓機制

  3. 線程狀態轉換開銷

    • BLOCKED→RUNNABLE狀態轉換需要系統介入

    • 這種轉換比保持RUNNABLE狀態有更高的延遲

2.?wait 和 notify

wait/notify 的本質作用

  • 應用層協作工具wait()?和?notify()?是 Java 提供的應用層線程協作機制,用于控制線程對共享資源的訪問順序,而非直接干預操作系統的線程調度策略。
  • 不改變調度規則:操作系統內核仍按自身調度算法(如輪轉法、優先級調度)決定線程何時獲得 CPU 時間,wait/notify?無法強制指定某個線程優先執行。

1.?wait()?法

wait(); 內部做的三件事:

1.?立即釋放鎖,無需等待同步塊結束

2. 線程狀態變化RUNNING?→?WAITING

3.?線程被喚醒后需重新獲取鎖,獲取成功后從?wait()?調用處繼續執行。WAITING→?BLOCKED(被喚醒后重新競爭鎖)→?RUNNING

線程狀態變化后,其他線程就有機會獲取鎖。

wait() 方法的三種重載形式

方法說明
wait()使當前線程無限期等待,直到另一個線程調用?notify()?或?notifyAll()?方法
wait(long timeout)指定一個超時時間,線程將在超時后自動被喚醒。線程也可以在超時前被?notify()?或?notifyAll()?方法喚醒。
wait(long timeout, int nanos)提供更高精度的超時設置,總超時時間(以納秒為單位)計算為?1_000_000*timeout + nanos

在 Java 中,調用?wait?方法的對象必須和鎖對象一致,這是因為?wait?方法的行為是基于對象的監視器(鎖)來實現的。以下是具體解釋:

  • 原理:當一個線程調用某個對象的?wait?方法時,該線程會釋放它所持有的該對象的鎖,并進入等待狀態,直到其他線程調用同一個對象的?notify?或?notifyAll?方法來喚醒它。如果調用?wait?方法的對象與獲取鎖的對象不一致,那么線程在等待時就無法正確地與該鎖關聯,也就無法按照預期被喚醒,并且可能會導致程序出現邏輯錯誤。

2.?notify()?法

方法說明
notify()喚醒等待該對象監視器的一個隨機線程。選擇喚醒哪個線程是非確定性的,取決于“隨機調度”算法
notifyAll()喚醒所有等待該對象監視器的線程。被喚醒的線程會和其他試圖獲取該對象鎖的線程一起競爭鎖

調用?notify()?或?notifyAll()?的對象必須與調用?wait()?的對象相同,并且它們必須與?synchronized?使用的鎖對象一致,否則會拋出?IllegalMonitorStateException

  1. wait()notify()notifyAll()?必須由同一個對象調用

  2. 必須在?synchronized?塊中使用,并且鎖對象必須與調用?wait()/notify()?的對象一致

每個 Java 對象都有一個監視器(monitor),也可以理解為鎖。當一個線程進入synchronized代碼塊時,它會獲取該代碼塊所關聯對象的鎖。wait方法會讓當前線程釋放這個鎖,并進入等待狀態,直到其他線程調用同一個對象的notifynotifyAll方法來喚醒它。而notifynotifyAll方法也需要在獲取相同對象的鎖之后才能調用,這樣它們才能準確地喚醒在該對象上等待的線程。如果這三個對象不一致,就會破壞這種線程同步機制,導致程序出現不可預測的結果,例如線程無法被喚醒、死鎖等問題。

wait()notify()?和?notifyAll()?方法必須在?synchronized?修飾的代碼塊或方法中調用,否則會拋出?IllegalMonitorStateException

1.?鎖與等待隊列的綁定

每個 Java 對象都有兩個核心屬性:

  • 監視器鎖(Monitor):用于實現同步。
  • 等待隊列(Wait Set):用于存儲調用?wait()?的線程。

wait()?和?notify()?的操作對象是對象的等待隊列,而等待隊列的狀態由來保護。因此,必須先獲取鎖才能操作等待隊列。

2.?原子性與可見性保障
public class SynchronizedDomo8 {public static void main(String[] args) throws InterruptedException {Object object = new Object();// 作為同步鎖和 wait/notify 的監視器對象Thread t1 = new Thread(()->{synchronized (object){// 獲取 object 的鎖System.out.println("t1 線程之前");// ①try {//必須使用同一個對象調用object.wait();// ② 釋放鎖,進入WAITING狀態} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("t1 線程之后");//  ⑦  被喚醒后重新獲取鎖,繼續執行}});Thread t2 = new Thread(()->{try {Thread.sleep(2000);// ③ 休眠 2 秒,確保 t1 先執行并進入 wait()} catch (InterruptedException e) {throw new RuntimeException(e);}synchronized (object){// 獲取 object 的鎖System.out.println("t2 線程之前");// ④//必須使用同一個對象調用object.notify();  // ⑤ 喚醒t1,但t2仍持有鎖System.out.println("t2 線程之后");// ⑥ 同步塊結束后釋放鎖}});t1.start();t2.start();}
}

執行步驟

  1. t1?進入?synchronized?塊,獲取?object?的鎖。

  2. 打印?"t1 線程之前"

  3. 調用?object.wait()

    • 釋放?object?的鎖t1?進入等待狀態。

  4. t2?先休眠 2 秒,確保?t1?先執行并進入?wait()?狀態。

  5. t2?進入?synchronized?塊,獲取?object?的鎖。

  6. 打印?"t2 線程之前"

  7. 調用?object.notify()

    • 喚醒?t1(WAITING -> BLOCKED),但?t1?不會立即執行,因為?t2?仍持有鎖。

  8. 打印?"t2 線程之后",退出?synchronized?塊,釋放鎖。

  9. t1?重新獲取鎖,繼續執行?"t1 線程之后"

3.?wait()、join()、sleep()方法的區別

方法sleep()join()wait()
所屬類Thread類Thread類?Object類?
釋放鎖???
喚醒條件?時間到期目標線程結束或超時notify()/notifyAll()或超時
使用限制?可以直接調用可以直接調用必須在同步塊中使用?
?拋出InterruptedException???
精度控制毫秒(實際精度依賴操作系統)?毫秒+納秒??毫秒+納秒?
線程狀態變化RUNNING → WAITINGRUNNING → TIMED_WAITINGRUNNING → WAITING/TIMED_WAITING

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/80323.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/80323.shtml
英文地址,請注明出處:http://en.pswp.cn/web/80323.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

MATLAB中heatmap函數

無論對表格還是對矩陣的可視化,都非常好用。 樣本特征 高斯核 https://ww2.mathworks.cn/help/matlab/creating_plots/create-heatmap-from-tabular-data.html

win11安裝Joplin Server私有化部署(docker)

摘要 本指南將幫助你在 Windows 11 系統 上通過 Docker Docker Compose 完成 Joplin Server 的本地搭建,并實現數據持久化、PostgreSQL 后端支持、用戶登錄與同步功能。 條件說明? 已安裝 Docker Desktop for Windows可從 Docker 官網 下載并安裝,建議…

嵌入式STM32學習——外部中斷EXTI與NVIC的基礎練習?

按鍵控制LED燈 按鍵控制LED的開發流程: 第一步:使能功能復用時鐘 第二布,配置復用寄存器 第三步,配置中斷屏蔽寄存器 固件庫按鍵控制LED燈 外部中斷EXTI結構體:typedef struct{uint32_t EXTI_Line; …

《Deepseek從入門到精通》清華大學中文pdf完整版

資源介紹: 《DeepSeek:從入門到精通》是由清華大學新聞與傳播學院新媒體研究中心元宇宙文化實驗室的精心撰寫的一份專業文檔。該文檔以通俗易懂的方 式,全面介紹了DeepSeek的使用方法,為用戶提供了極具價值的指導。 這份文檔內容豐…

Apache Pulsar 消息、流、存儲的融合

Apache Pulsar 消息、流、存儲的融合 消息隊列在大層面有兩種不同類型的應用,一種是在線系統的message queue,一種是流計算,data pipeline的streaming高throughout,一致性較低,延遲較差的過程。 存算分離 擴容和縮容快…

JavaScript vs Python 用于 Web Scraping(2025):終極對比指南

1. 引言 在不斷發展的 Web Scraping 領域,選擇合適的編程語言對于項目的成功至關重要。雖然 JavaScript 和 Python 在 2025 年仍然是 Web Scraping 領域的熱門選擇,但它們各自具備不同的優勢和挑戰。 本指南將深入分析 JavaScript 和 Python 的核心特性…

【RocketMQ Broker 相關源碼】- NettyRemotingClient 和 NettyRemotingServer

文章目錄 1. 前言2. BrokerOuterAPI2.1 NettyRemotingClient2.2 start 啟動2.2.1 NettyRemotingClient#start 3. NettyRemotingServer3.1 ClientHousekeepingService3.2 ProducerManager#doChannelCloseEvent3.3 ConsumerManager#doChannelCloseEvent3.3.1 DefaultConsumerIdsC…

C++性能測試工具——AMD CodeAnalyst及其新工具的使用

一、CodeAnalyst及其新的替代工具 與VTune相比,AMD也有自己的性能測試工具,也就是CodeAnalyst。不過目前看,其應該已經有些過時,目前AMD提供了更新的性能測試工具uProf或CodeXL,這些新工具的優點在于對新的硬件架構和…

ProfibusDP主站轉modbusTCP網關與ABB電機保護器數據交互

ProfibusDP主站轉modbusTCP網關與ABB電機保護器數據交互 在工業自動化領域,Profibus DP(Process Field Bus)和Modbus TCP是兩種常見的通訊協議,它們各自在不同的場合發揮著重要作用。然而,隨著技術的發展和應用需求的…

2025.05.17淘天機考筆試真題第三題

📌 點擊直達筆試專欄 👉《大廠筆試突圍》 💻 春秋招筆試突圍在線OJ 👉 筆試突圍OJ 03. 奇偶平衡樹分割問題 問題描述 K小姐是一位園林設計師,她設計了一個由多個花壇組成的樹形公園。每個花壇中種植了不同數量的花…

第三十五節:特征檢測與描述-ORB 特征

1. 引言:為什么需要ORB? 在計算機視覺領域,特征檢測與描述是許多任務(如圖像匹配、目標跟蹤、三維重建等)的核心基礎。傳統的算法如SIFT(尺度不變特征變換)和SURF(加速穩健特征)因其優異的性能被廣泛應用,但它們存在兩個顯著問題: 專利限制:SIFT和SURF受專利保護,…

深入解讀WPDRRC信息安全模型:構建中國特色的信息安全防護體系

目錄 前言1 WPDRRC模型概述2 模型結構詳解2.1 預警(Warning)2.2 保護(Protect)2.3 檢測(Detect)2.4 響應(React)2.5 恢復(Restore)2.6 反擊(Count…

《算法導論(第4版)》閱讀筆記:p82-p82

《算法導論(第4版)》學習第 17 天,p82-p82 總結,總計 1 頁。 一、技術總結 1. Matrix Matrices(矩陣) (1)教材 因為第 4 章涉及到矩陣,矩陣屬于線性代數(linear algebra)范疇,如果不熟悉,可以看一下作者推薦的兩本…

基于Spring Boot和Vue的在線考試系統架構設計與實現(源碼+論文+部署講解等)

源碼項目獲取聯系 請文末卡片dd我獲取更詳細的演示視頻 系統介紹 基于Spring Boot和Vue的在線考試系統。為學生和教師/管理員提供一個高效、便捷的在線學習、考試及管理平臺。系統采用前后端分離的架構,后端基于成熟穩定的Spring Boot框架,負責數據處理…

Codeforces Round 1024 (Div.2)

比賽鏈接&#xff1a;CF1024 A. Dinner Time 只有當 n n n 是 p p p 的倍數而且 n ? q p ? m \frac{n \cdot q}{p} \not m pn?q?m 時輸出 NO&#xff0c;其余情況均滿足條件。 時間復雜度&#xff1a; O ( 1 ) O(1) O(1)。 #include <bits/stdc.h> using na…

【LeetCode 熱題 100】二叉樹的最大深度 / 翻轉二叉樹 / 二叉樹的直徑 / 驗證二叉搜索樹

??個人主頁&#xff1a;小羊 ??所屬專欄&#xff1a;LeetCode 熱題 100 很榮幸您能閱讀我的文章&#xff0c;誠請評論指點&#xff0c;歡迎歡迎 ~ 目錄 二叉樹的中序遍歷二叉樹的最大深度翻轉二叉樹對稱二叉樹二叉樹的直徑二叉樹的層序遍歷將有序數組轉換為二叉搜索樹驗…

Tomcat發布websocket

一、tomcal的lib放入文件 tomcat-websocket.jar websocket-api.jar 二、代碼示例 package com.test.ws;import com.test.core.json.Jmode;import javax.websocket.*; import javax.websocket.server.ServerEndpoint; import java.util.concurrent.CopyOnWriteArraySet; imp…

LLM筆記(二)LLM數據基礎-分詞算法(2)

文章目錄 1. 分詞算法概述1.1 基于詞典的&#xff08;或基于規則的&#xff09;分詞算法1.2 基于統計的&#xff08;或基于機器學習的&#xff09;分詞算法1.3 基于深度學習的分詞算法1.4 子詞&#xff08;Subword&#xff09;分詞算法1.5 混合分詞算法1.6 針對不同語言的特點 …

Uniapp開發鴻蒙應用時如何運行和調試項目

經過前幾天的分享&#xff0c;大家應該應該對uniapp開發鴻蒙應用的開發語法有了一定的了解&#xff0c;可以進行一些簡單的應用開發&#xff0c;今天分享一下在使用uniapp開發鴻蒙應用時怎么運行到鴻蒙設備&#xff0c;并且在開發中怎么調試程序。 運行 Uniapp項目支持運行到…

數據湖與數據倉庫融合:Hudi、Iceberg、Delta Lake 實踐對比

在實時與離線一體化的今天,數據湖與數據倉庫邊界不斷融合,越來越多企業選用如 Hudi、Iceberg、Delta Lake 等開源方案實現統一的數據存儲、計算、分析平臺。本篇將圍繞以下關鍵點,展開實戰對比與解決方案分享: ? 實時寫入能力 ? ACID 保證 ? 增量數據處理能力 ? 流批一…