目錄
1.wait(),notify(),notifyall()
2.生產者消費者模式
3.多生產多消費模式
1.wait(),notify(),notifyall()
object類為我們定義了執行緒通訊的方法,如wait(),notify()等,這些方式是本地的而且是final的.
1.1wait()
1)呼叫wait()方法,能讓當前執行緒阻塞並交出此物件的monitor,然後進入等待狀態直到其他執行緒呼叫此物件的notify()或notifyall()方法.當前的執行緒必須擁有此物件的monitor,也就是說wait()方法需要在synchronized域內使用.
2)wait()和sleep()的區別
wait
sleep
所屬類
thread
object
物件鎖
釋放
不釋放使用環境
synchronized域內
任意環境
喚醒方式
通過notify或notifyall喚醒
休眠到指定時間自動喚醒
1.2notify(),notifyall()
調notify()方法能夠喚醒乙個正在等待這個物件的monitor的某乙個執行緒,notifyall()方法能夠喚醒所有正在等待這個物件的monitor的執行緒.同樣的,這兩個方法需要在synchronized域內使用,也不會釋放鎖,.
2.生產者消費者模式
生產者消費者模式是經典的執行緒通訊模式,其主旨為兩個執行緒交替對乙個共享資源進行操作,並相互進行通訊.例:
public class threaddemo
}// 資源類
class resource catch (interruptedexception e)
}count++;
system.out.println("生產者行為..." + count);
flag = true;
notify();
}public synchronized void get() catch (interruptedexception e)
}system.out.println("消費者行為......" + count);
flag = false;
notify();}}
// 生產者執行緒
class producer implements runnable
@override
public void run() }}
// 消費者執行緒
class consumer implements runnable
@override
public void run()
}}
執行結果:生產者消費者交替執行,每次對應的行為計數(count)相同.
3.多生產多消費模式
現實生活中長對應多個生產者和多個消費者,因此我們可以增加執行緒來實現.在上一節的main()函式內增加多個執行緒,例:
public class threaddemo
}
執行結果:生產者消費者執行過程中偶爾會執行多次同一行為:
生產者行為...41133
消費者行為......41133
消費者行為......41133
我們已經使用了synchronized了,究竟是**出錯了呢?讓我們重新來看消費者的行為**:
public synchronized void get() catch (interruptedexception e)
}system.out.println("消費者行為......" + count);// 3
flag = false;// 4
notify();// 5
}
假設消費者c1呼叫了get()方法並得到了當前物件的鎖,執行**第1行進行if判斷》如果if語句判斷為true,c1進入等待狀態並釋放當前物件鎖》當其他執行緒呼叫了notify()喚醒c1後,c1繼續執行之前的任務,執行**第345行.問題就是在這裡出現的,因為c1再次執行時沒有進行flag標誌位的判斷而繼續執行,而如果此時flag標誌位不滿足條件時,列印的資料就是錯的.為了使執行緒再被喚醒後能再次對標誌位進行判斷,我們可以將if語句改為while語句.例:
public synchronized void get() catch (interruptedexception e)
}system.out.println("消費者行為......" + count);// 3
flag = false;// 4
notify();// 5
}
修改後再次執行,程式執行一會後阻塞了,又是為什麼呢?再次分析修改後的**:
消費者c1正常執行後呼叫了notify()方法》由於notify()方法只能喚醒某乙個等待執行緒,如果喚醒的是另乙個消費者c2,c2獲得執行權》由於flag標誌位沒變,因此c2也會進入等待狀態.但是如果這是最後乙個非等待狀態的執行緒,那麼所有執行緒都會處於wait()狀態從而阻塞.也就是說,這次是notify()引起的問題,如果notify()喚醒的是本方執行緒,那麼是沒有意義的,因此我們可以使用notifyall()喚醒所有執行緒,從而達到喚醒對方執行緒的目的.再次修改後的**:
public synchronized void put() catch (interruptedexception e)
}count++;
system.out.println(thread.currentthread().getname() + "生產者行為..." + count);
flag = true;
notifyall();
}public synchronized void get() catch (interruptedexception e)
}system.out.println(thread.currentthread().getname() + "消費者行為......" + count);
flag = false;
notifyall();
}
執行結果:多生產者之間和多消費者之間是隨機執行的,但每乙個生產者和乙個消費者對應並執行同樣的計數行為.
總結:在多生產多消費模式中,需通過while判斷和notifyall()喚醒所有執行緒,以實現通訊功能.notifyall()雖然達到了喚醒對方的目的,但同時也喚醒了所有本方的執行緒,因此也是影響效能的,在後面的高階併發物件中我們會解決這樣的問題.
java併發 執行緒通訊 9
需要通訊的多種方式以及注意事項請移步 執行緒通訊方式 1 多個執行緒之間通過共享變數通訊。也就是a執行緒修改了變數x 11,b執行緒拿到x的值就是a修改之後的值11。這也是執行緒之間的間接通訊。2.通過方法wait,notiy,notifiall.wait a執行緒呼叫了該方法,那麼a執行緒將沉睡,...
Java併發程式設計 執行緒通訊
1.wait和notify方法 配合synchronize使用,屬於object方法 private volatile static list list new arraylist public void add public int size public static void main str...
java 執行緒 執行緒的通訊
執行緒通訊的三種方式 同步 while 輪詢方式 wait notify 方式 這裡講的同步是synchronized 關鍵字來實現執行緒間的通訊,我們用 來示範一下。class obj public synchronized void del public class demo4 start 執行...