執行緒間通訊_等待/通知機制
等待/通知的相關方法式任意java物件都具備的,notify,wait方法被定義在java.lang.Object,都是final,不可重寫
,是例項方法,新手比較容易出錯的地方是,呼叫時候必須呼叫 鎖物件.wait()/鎖物件.nofity(),並且只能在臨界區中呼叫
具體瞭解下,notify,wait定義
名稱 | 描述 |
notify() | 通知在同一個物件上等待的執行緒,使其從wait()方法返回,而返回的前提是該執行緒獲取到物件的鎖 |
notifyAll() | 通知所有等待同一個物件鎖的執行緒 |
wait() | 呼叫該方法的執行緒進入WAITING狀態,並且釋放物件的鎖,從方法描述上可以看出是響應中斷的/或者接收到notify才會返回 |
wait(long) | 超時等待一段時間,沒有接受到通知就超時返回 |
wait(long,int) | 對於超時時間更細粒度的控制,可以達到納秒 |
等待/通知機制,舉個例子來說執行緒A呼叫物件obj的wait方法進入WAITING狀態,另一個執行緒呼叫同一個物件的notify方法喚醒執行緒A,執行緒A繼續執行wait後的程式
簡單的案例 ,單個生產者、單個消費者
鎖物件:
package com.ftf.thread.test;
public class Student {
public volatile boolean flag;
public Student(boolean flag) {
this.flag = flag;
}
}
生產者:
package com.ftf.thread.test;
public class Product {
private Student obj;
public Product(Student obj) {
this.obj = obj;
}
public void dothis() {
synchronized (obj) {
try{
if(!obj.flag) {
obj.wait();
}
System.out.println("我是生產者執行緒"
+ Thread.currentThread().getName());
Thread.sleep(1000);
obj.flag = false;
obj.notify();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
消費者執行緒:
package com.ftf.thread.test;
public class Customer {
private Student obj;
public Customer(Student obj) {
this.obj = obj;
}
public void dothis() {
synchronized (obj) {
try {
if(obj.flag) {
obj.wait();
}
System.out.println("我是消費者執行緒"
+ Thread.currentThread().getName());
Thread.sleep(1000);
obj.flag = true;
obj.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
main方法:
package com.ftf.thread.test;
public class NotifyWaitDemo {
public static void main(String[] args) {
Student obj = new Student(true);
Product notify = new Product(obj);
Customer wait = new Customer(obj);
Thread1 t1 = new Thread1(notify);
Thread2 t4 = new Thread2(wait);
t1.start();
t4.start();
}
}
class Thread1 extends Thread{
private Product notify;
public Thread1(Product notify){
this.notify= notify;
}
@Override
public void run() {
while(true){
notify.dothis();
}
}
}
class Thread2 extends Thread{
private Customer wait;
public Thread2(Customer wait){
this.wait = wait;
}
@Override
public void run() {
while(true){
wait.dothis();
}
}
}
說明:
1.通過類Student flag定義為volatile這樣,通過記憶體可見性,兩個執行緒修改這個值,另一個執行緒都能看到,來控制兩個執行緒釋放鎖和獲取鎖互動
2. 在單個消費者, 單個生產者和使用notify的情況下,使用if判斷沒有問題
多個生產者,多個消費者需要使用while作為條件判斷
驗證在多生產者消費者情況下,使用if存在的問題
生產者dothis方法修改: while->if,因為是多個生產者消費者,需要將notify->notifyAll
public void dothis() {
synchronized (obj) {
try{
if (!obj.flag) {
obj.wait();
}
System.out.println("我是生產者執行緒"
+ Thread.currentThread().getName());
Thread.sleep(1000);
obj.flag = false;
obj.notifyAll();
}catch(InterruptedException e){
e.printStackTrace();
}
}
同樣,修改消費者程式碼
public void dothis() {
synchronized (obj) {
try {
if (obj.flag) {
obj.wait();
}
System.out.println("我是消費者執行緒"
+ Thread.currentThread().getName());
Thread.sleep(1000);
obj.flag = true;
obj.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
,修改main方法:
public static void main(String[] args) {
Student obj = new Student(true);
Product notify = new Product(obj);
Customer wait = new Customer(obj);
Thread1 t1 = new Thread1(notify);
Thread1 t2 = new Thread1(notify);
Thread2 t3 = new Thread2(wait);
Thread2 t4 = new Thread2(wait);
t1.start();
t2.start();
t3.start();
t4.start();
}
測試結果:
出現了,消費者執行緒連續消費兩次的情況。
說明:
在多生產者,多消費者情況下,對於wait方法的判斷使用while條件判斷,而不是使用if,
是為了防止在多生產者,多消費者的情況下,如果使用if的條件,當前執行緒釋放鎖後,再次獲取到鎖後,
不進行檢查flag,直接往下執行,那本例來說,就是消費者執行緒釋放掉鎖後,再次獲取到鎖,再次消費
相關文章
- Java 執行緒間通訊 —— 等待 / 通知機制Java執行緒
- Java併發程式設計(04):執行緒間通訊,等待/通知機制Java程式設計執行緒
- 多執行緒之等待通知機制執行緒
- 執行緒間通訊_等待/通知之Thread.join()執行緒thread
- Java多執行緒之三volatile與等待通知機制示例Java執行緒
- Java多執行緒學習(四)等待/通知(wait/notify)機制Java執行緒AI
- 大話Android多執行緒(三) 執行緒間的通訊機制之HandlerAndroid執行緒
- 執行緒4--執行緒間通訊執行緒
- 執行緒間的通訊執行緒
- 一起分析執行緒的狀態及執行緒通訊機制執行緒
- Android執行緒間通訊Android執行緒
- java多執行緒5:執行緒間的通訊Java執行緒
- 多執行緒之間通訊及執行緒池執行緒
- 說說Java執行緒間通訊Java執行緒
- JUC之執行緒間的通訊執行緒
- 多執行緒之間的通訊執行緒
- java多執行緒間的通訊Java執行緒
- 執行緒通訊機制:共享記憶體 VS 訊息傳遞執行緒記憶體
- 執行緒間的協作機制執行緒
- 程式間通訊機制(管道、訊號、共享記憶體/訊號量/訊息佇列)、執行緒間通訊機制(互斥鎖、條件變數、posix匿名訊號量)記憶體佇列執行緒變數
- 程式通訊 執行緒通訊執行緒
- Java-執行緒間通訊小結Java執行緒
- iOS GCD執行緒之間的通訊iOSGC執行緒
- Java多執行緒-執行緒通訊Java執行緒
- Android執行緒間訊息機制-Handler原始碼分析(FrameWork)Android執行緒原始碼Framework
- JUC之執行緒間定製化通訊執行緒
- Android開發之執行緒間通訊Android執行緒
- Java執行緒通訊Java執行緒
- java多執行緒:執行緒間通訊——生產者消費者模型Java執行緒模型
- 【Java】【多執行緒】兩個執行緒間的通訊、wait、notify、notifyAllJava執行緒AI
- 徹底明白Java的多執行緒-執行緒間的通訊(2)(轉)Java執行緒
- 徹底明白Java的多執行緒-執行緒間的通訊(1)(轉)Java執行緒
- Java併發之等待/通知機制Java
- Java多執行緒學習——執行緒通訊Java執行緒
- 執行緒同步機制執行緒
- Java中快如閃電的執行緒間通訊Java執行緒
- Swift多執行緒:使用Thread進行多執行緒間通訊,協調子執行緒任務Swift執行緒thread
- Android小知識-Java多執行緒相關(執行緒間通訊)上篇AndroidJava執行緒