Java多線程中的wait、notify和park、unpark的使用詳解
一、wait & notify的使用
1、API介紹
- obj.wait() 讓進(jìn)入 object 監(jiān)視器的線程到 waitSet 等待
- obj.wait(n) 讓進(jìn)入 object 監(jiān)視器的線程到 waitSet 等待,n秒后還沒有被喚醒的話,則自動醒來
- obj.notify() 在 object 上正在 waitSet 等待的線程中挑一個(gè)喚醒
- obj.notifyAll() 讓 object 上正在 waitSet 等待的線程全部喚醒
它們都是線程之間進(jìn)行協(xié)作的手段,都屬于 Object 對象的方法。
必須獲得此對象的鎖,才能調(diào)用這幾個(gè)方法 wait() 方法會釋放對象的鎖,進(jìn)入 WaitSet 等待區(qū),從而讓其他線程就機(jī)會獲取對象的鎖。
無限制等待,直到notify 為止 wait(long n) 有時(shí)限的等待, 到 n 毫秒后結(jié)束等待,或是被 notify notify 只能隨機(jī)喚醒一個(gè) WaitSet 中的線程,這時(shí)如果有其它線程也在等待,那么就可能喚醒不了正確的線程,稱之為【虛假喚醒】
2、demo
@Slf4j(topic = "c.TestCorrectPosture") public class TestCorrectPostureStep5 { static final Object room = new Object(); static boolean hasCigarette = false; static boolean hasTakeout = false; public static void main(String[] args) { new Thread(() -> { synchronized (room) { log.debug("有煙沒?[{}]", hasCigarette); while (!hasCigarette) { log.debug("沒煙,先歇會!"); try { room.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } log.debug("有煙沒?[{}]", hasCigarette); if (hasCigarette) { log.debug("可以開始干活了"); } else { log.debug("沒干成活..."); } } }, "小南").start(); new Thread(() -> { synchronized (room) { Thread thread = Thread.currentThread(); log.debug("外賣送到?jīng)]?[{}]", hasTakeout); while (!hasTakeout) { log.debug("沒外賣,先歇會!"); try { room.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } log.debug("外賣送到?jīng)]?[{}]", hasTakeout); if (hasTakeout) { log.debug("可以開始干活了"); } else { log.debug("沒干成活..."); } } }, "小女").start(); sleep(1); new Thread(() -> { synchronized (room) { hasTakeout = true; log.debug("外賣到了噢!"); room.notifyAll(); } }, "送外賣的").start(); } }
2、多線程模式
模式之保護(hù)性暫停 模式之生產(chǎn)者消費(fèi)者
3、wait和notify的原理
二、Park & Unpark的使用
1、基本使用
它們是 LockSupport 類中的方法
// 暫停當(dāng)前線程 LockSupport.park(); // 恢復(fù)某個(gè)線程的運(yùn)行 LockSupport.unpark(暫停線程對象)
先 park 再 unpark
public static void main(String[] args) { Thread t1 = new Thread(() -> { log.debug("start..."); sleep(1); log.debug("park..."); LockSupport.park(); log.debug("resume..."); }, "t1"); t1.start(); sleep(4); log.debug("unpark..."); LockSupport.unpark(t1); }
先 unpark 再 park
public static void main(String[] args) { Thread t1 = new Thread(() -> { log.debug("start..."); sleep(2); log.debug("park..."); LockSupport.park(); log.debug("resume..."); }, "t1"); t1.start(); sleep(1); log.debug("unpark..."); LockSupport.unpark(t1); }
結(jié)論:park和unpark是成對出現(xiàn),但是是不分先后的
2、特點(diǎn)
與 Object 的 wait & notify 相比
- wait,notify 和 notifyAll 必須配合 Object Monitor 一起使用,而 park,unpark 不必
- park & unpark 是以線程為單位來【阻塞】和【喚醒】線程(喚醒的時(shí)候可以傳一個(gè)線程作為參數(shù)),而 notify 只能隨機(jī)喚醒一個(gè)等待線程,notifyAll 是喚醒所有等待線程,就不那么【精確】
- park & unpark 可以先 unpark,而 wait & notify 不能先 notify
到此這篇關(guān)于Java多線程中的wait、notify和park、unpark的使用詳解的文章就介紹到這了,更多相關(guān)Java多線程wait、notify和park內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
關(guān)于jackson序列化和feign返回值的問題
這篇文章主要介紹了關(guān)于jackson序列化和feign返回值的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03SpringCloud容器化服務(wù)發(fā)現(xiàn)及注冊實(shí)現(xiàn)方法解析
這篇文章主要介紹了SpringCloud容器化服務(wù)發(fā)現(xiàn)及注冊實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08你應(yīng)該知道的21個(gè)Java核心技術(shù)
Java的21個(gè)核心技術(shù)點(diǎn),你知道嗎?這篇文章主要為大家詳細(xì)介紹了Java核心技術(shù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-08-08解決mac最新版intellij idea崩潰閃退crash的問題
這篇文章主要介紹了解決mac最新版intellij idea崩潰閃退crash的問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09java使double保留兩位小數(shù)的多方法 java保留兩位小數(shù)
這篇文章主要介紹了java使double類型保留兩位小數(shù)的方法,大家參考使用吧2014-01-01