1. 程式人生 > >多執行緒中wait(),notify()和notifyall()方法的含義

多執行緒中wait(),notify()和notifyall()方法的含義

在“synchronized(obj){··········}”這個同步塊中,obj物件叫做監控器,只有持有監控器這個物件的鎖時才會執行同步塊中的內容

Java中的執行緒的生命週期大體可分為5種狀態。

1. 新建(NEW):新建立了一個執行緒物件。

2. 可執行(RUNNABLE):執行緒物件建立後,其他執行緒(比如main執行緒)呼叫了該物件的start()方法。該狀態的執行緒位於可執行執行緒池中,等待被執行緒排程選中,獲取cpu 的使用權 。

3. 執行(RUNNING):可執行狀態(runnable)的執行緒獲得了cpu 時間片(timeslice) ,執行程式程式碼。
4. 阻塞(BLOCKED)
:阻塞狀態是指執行緒因為某種原因放棄了cpu 使用權,也即讓出了cpu timeslice,暫時停止執行。直到執行緒進入可執行(runnable)狀態,才有機會再次獲得cpu timeslice 轉到執行(running)狀態。阻塞的情況分三種: 
(一). 等待阻塞:執行(running)的執行緒執行o.wait()方法,JVM會把該執行緒放入等待佇列(waitting queue)中。
(二). 同步阻塞:執行(running)的執行緒在獲取物件的同步鎖時,若該同步鎖被別的執行緒佔用,則JVM會把該執行緒放入鎖池(lock pool)中。
(三). 其他阻塞:執行(running)的執行緒執行Thread.sleep(long ms)或t.join()方法,或者發出了I/O請求時,JVM會把該執行緒置為阻塞狀態。當sleep()狀態超時、join()等待執行緒終止或者超時、或者I/O處理完畢時,執行緒重新轉入可執行(runnable)狀態。

5. 死亡(DEAD):執行緒run()、main() 方法執行結束,或者因異常退出了run()方法,則該執行緒結束生命週期。死亡的執行緒不可再次復生。


     wait(),notify()和notifyall()方法是Object類物件的方法,所以所有的物件都可以作為監控器


public class WaitNotify {
			static boolean flag = true;
			static Object lock = new Object() ;
			public static void main(String[ ] args) throws Exception {
				Thread waitThread = new Thread(new Wait() , "WaitThread") ;
				waitThread. start() ;
				TimeUnit. SECONDS. sleep(1) ;
				Thread notifyThread = new Thread(new Notify() , "NotifyThread") ;
				notifyThread. start() ;
			}
			static class Wait implements Runnable {
			public void run() {
			// 加鎖, 擁有lock的Monitor
				synchronized (lock) {
				// 當條件不滿足時,繼續wait, 同時釋放了lock的鎖
					while (flag) {
						try {
							System.out.println(Thread.currentThread() + "flag is true. 
[email protected]
" + new SimpleDateFormat("HH: mm: ss").format(new Date())) ; lock. wait() ; } catch (InterruptedException e) { } } // 條件滿足時, 完成工作 System.out.println(Thread.currentThread() +" flag is false. [email protected] " + new SimpleDateFormat("HH: mm: ss").format(new Date())) ; } } } static class Notify implements Runnable { public void run() { // 加鎖,擁有lock的Monitor synchronized (lock) { // 獲取lock的鎖, 然後進行通知, 通知時不會釋放lock的鎖, // 直到當前執行緒釋放了lock後, WaitThread才能從wait方法中返回 System.out.println(Thread. currentThread() + " hold lock. notify @ " + new SimpleDateFormat("HH: mm: ss") . format(new Date() ) ) ; lock.notifyAll() ; flag = false; SleepUtils.second(5) ; } // 再次加鎖 synchronized (lock) { System.out.println(Thread.currentThread() + "hold lock again. sleep"+ new SimpleDateFormat("HH: mm: ss").format(new Date() ) ) ; SleepUtils.second(5) ; } } } }

呼叫wait()、 notify()以及notifyAll()時需要注意的細節, 如下。
1) 使用wait()、notify()和notifyAll()時需要先對呼叫物件加鎖。
2) 呼叫wait()方法後, 執行緒狀態由 RUNNING變為WAITING, 並將當前執行緒放置到物件的
等待佇列。
3) notify()或notifyAll()方法呼叫後, 等待執行緒依舊不會從wait()返回, 需要呼叫notify()或
notifAll()的執行緒釋放鎖之後, 等待執行緒才有機會從wait()返回。
4) notify()方法將等待佇列中的一個等待執行緒從等待佇列中移到同步佇列中, 而notifyAll()
方法則是將等待佇列中所有的執行緒全部移到同步佇列, 被移動的執行緒狀態由 WAITING變為
BLOCKED。
5) 從wait()方法返回的前提是獲得了呼叫物件的鎖。

要注意的一點就是執行nitifyAll()方法時不會立刻就釋放物件的鎖,而是要等到執行緒執行完成後才會釋放

但是執行wait()方法時就是會立刻釋放物件的鎖,然後當前執行緒就會卡在wait()方法處,等待喚醒

另外還有一點需要提的是這三個方法都必須被包裹在同步塊中!

相關推薦

執行wait(),notify()notifyall()方法含義

在“synchronized(obj){··········}”這個同步塊中,obj物件叫做監控器,只有持有監控器這個物件的鎖時才會執行同步塊中的內容Java中的執行緒的生命週期大體可分為5種狀態。1. 新建(NEW):新建立了一個執行緒物件。2. 可執行(RUNNABLE)

執行waitsleep區別

wiat和sleep的區別? 1、wait可以指定時間也可以不指定      sleep必須指定時間。 2、在同步中,對cpu的執行權和鎖的處理不同 wait:釋 放執行權,釋放鎖。 slee

【原】對執行WaitJoin的理解

對於,wait方法的解釋,有時候覺得很矛盾。呼叫某個物件的wait時,需要獲得該物件的鎖,在執行的時候又需要釋放該物件的所有鎖。這是問題一。 另外,在看Join的原始碼,會發現它利用了Wait來實現,但是它的實現原理是怎樣的呢? 這是問題二。 看下原始碼的英文描述:

Java執行Synchronized簡介Static Synchronized的區別

在進行Java開發時,多執行緒的開發是經常會使用的。首先會問一個小問題啊,在Java中有幾種方法可以建立一個執行緒? 我給的答案是3種。(如果還有其他的請留言告訴我哈。) 1、建立直接繼承自Thread類建立執行緒子類。   步驟如下:a 定義一個子類,同時

7.併發程式設計--執行通訊-wait-notify

併發程式設計--多執行緒通訊-wait-notify 多執行緒通訊:執行緒通訊的目的是為了能夠讓執行緒之間相互發送訊號; 1. 多執行緒通訊: 執行緒通訊的目的是為了能夠讓執行緒之間相互發送訊號。另外,執行緒通訊還能夠使得執行緒等待其它執行緒的訊號,比如,執行緒B可以等待執行緒A的訊號,這個訊號可以是執

執行synchronized, wait, notify, sleep 理解

最近在看多執行緒,參考了一篇 部落格 ,覺得寫得比較好,但是在一段相關物件鎖的程式碼上卡住了,理解不了,問了同學,加上自己的理解,終於搞懂了。 測試程式碼 package com.fehead.test; import com.fehead.thread.MyThrea

執行總記憶體執行的工作記憶體

Java記憶體模型將記憶體分為了 主記憶體和工作記憶體 。類的狀態,也就是類之間共享的變數,是儲存在主記憶體中的,每個執行緒都有一個自己的工作記憶體(相當於CPU高階緩衝區,這麼做的目的還是在於進一步縮小儲存系統與CPU之間速度的差異,提高效能),每次Java

_159_java_執行wait/notify

本文主要學習JAVA多執行緒中的 wait()方法 與 notify()/notifyAll()方法的用法。 ①wait() 與 notify/notifyAll 方法必須在同步程式碼塊中使用 ②wait() 與  notify/notifyAll() 的執行過程 ③中斷 呼叫

Java執行的finalstatic

看Android的多執行緒發現其實是Java的多執行緒。我找了一本Java程式設計思想學習Java的併發機制。寫了一個demo,遇到一些問題,雖然最後想明白了,但是也暴露了我的Java基礎差勁的事實。之後我會通過寫部落格的方式來提高Java水平。現在說一下我的問

muduo網路庫學習之EventLoop(二):程序(執行wait/notify EventLoop::runInLoop

// 事件迴圈,該函式不能跨執行緒呼叫 // 只能在建立該物件的執行緒中呼叫void EventLoop::loop() {// 斷言當前處於建立該物件的執行緒中  assertInLoopThread();     while (!quit_)     {         pollReturnTime_ =

iOS執行,佇列執行的排列組合結果分析

本文是對以往學習的多執行緒中知識點的一個整理。 多執行緒中的佇列有:序列佇列,併發佇列,全域性佇列,主佇列。 執行的方法有:同步執行和非同步執行。那麼兩兩一組合會有哪些注意事項呢? 如果不是在董鉑然部落格園看到這邊文章請 點選檢視原文 提到多執行緒,也就是四種,pthread,NSthread,GCD

JAVA執行wait/notify

本文主要學習JAVA多執行緒中的 wait()方法 與 notify()/notifyAll()方法的用法。 ①wait() 與 notify/notifyAll 方法必須在同步程式碼塊中使用 ②wait() 與  notify/notifyAll() 的執行過程 ③中斷 呼叫wait()方法進入等待佇

Java執行,JoinInterrupt()方法的使用

更多詳細的解答請轉至:http://my.oschina.net/summerpxy/blog/198457;http://uule.iteye.com/blog/1101994;(比如有一個執行緒t.當在Main執行緒中呼叫t.join()的時候,那麼Main執行緒必須拿

java之執行Thread類Runnable介面使用方法

java提供了兩種執行緒方式,一種是繼承java.lang包下的Thread類,覆寫Thread類的run()方法,在run()方法中實現執行線上程上的程式碼!第二種是實現Runnable介面建立多執行

Java執行wait,notify,sleep,,yield,join,suspend,resume

Java中的多執行緒是一種搶佔式的機制而不是分時機制。執行緒主要有以下幾種狀態:可執行,執行,阻塞,死亡。搶佔式機制指的是有多個執行緒處於可執行狀態,但是隻有一個執行緒在執行。 當有多個執行緒訪問共享資料的時候,就需要對執行緒進行同步。執行緒中的幾個主要方法的比較:

java執行的sleep()、wait()、notify()物件鎖的關係

1、sleep()不釋放物件鎖。 2、wait()釋放物件鎖。 3、notify()不釋放物件鎖。 (1)、notify釋放鎖嗎?不要誤導別人。notifty()只是喚醒此物件監視器上等待的單個執行緒,直到當前執行緒釋放此物件上的鎖,才有可能繼續執行被喚醒的執行緒。 (2)

執行wait()notify()方法

wait()和notify()方法屬於Object類中的方法,是用於對執行緒之間進行資源物件鎖的通訊,其必須在synchronized(Obj){...}語法塊內 wait()就是說執行緒在獲取物件鎖後,主動釋放物件鎖,同時本執行緒進行休眠。直到有其它執行緒呼叫該物件的no

Java 內部類,執行Synchronized與wait,notify的使用

工作內容: 1.成員內部類    與成員方法,屬性的訪問許可權一致 2.靜態內部類    修飾符 stactic 類名{...} 3.匿名內部類    new 類名()/介面名(重寫介面方法) 4.區域性內部類    程式碼塊中 5.執行緒Thread wait,noti

執行waitnotify功能演示

wait(), notify(), notifyAll()等方法介紹 在Object.java中,定義了wait(), notify()和notifyAll()等介面。wait()的作用是讓當前執行緒進入等待狀態,同時,wait()也會讓當前執行緒釋放它所持有的鎖。

java 執行suspend()、resume()wait()、notify()的區別

初看起來它們與 suspend() 和 resume() 方法對沒有什麼分別,但是事實上它們是截然不同的。區別的核心在於,前面敘述的所有方法,阻塞時都不會釋放佔用的鎖(如果佔用了的話),而這一對方法則相反。 上述的核心區別導致了一系列的細節上的區別。     首先,前面敘述的所有方法都隸屬於 Thread