javase學習記錄之------生成者消費者之等待喚醒機制
package src;
/*
分析:
資源類:Student
設定學生資料:SetThread(生產者)
獲取學生資料:GetThread(消費者)
測試類:StudentDemo
問題1:按照思路寫程式碼,發現資料每次都是null---0
原因:我們在每個執行緒中都建立了新的資源(新的學生類物件),而我們的要求是獲取執行緒的資源應該是同一個
如何實現呢?
通過外界把這個資料建立出來,通過構造方法傳遞給其他類。
問題2:為了資料的效果更好一些,我加入了迴圈和判斷,給了不同的值,這個時候產生了新的問題
1:同一個資料出現多次
2:姓名和年齡不匹配
原因:
1:同一個資料出現多次
SetThread搶到一次,此時是林青霞27,然後就一直是GetThread搶到,所以就一直輸出這個
CPU的一點點時間片的執行權,就足夠執行很多次
2:姓名和年齡不匹配
SetThread搶到執行權,此時X=1,走到 s.setName("周志武");然後就被別人搶了執行權,但是年齡還沒來得及改,所以就變成了周志武27
如果是個整體就不會出現這種情況了
總的來說就是執行緒執行的隨機性導致的
執行緒安全問題:
1:是否是多執行緒環境 是
2:是否又共享資料 是
3:是否又多條語句共享資料 是 符合產生問題的條件
解決方案:
加鎖!
注意:
1:不同種類的執行緒都要加鎖
2:不同種類的執行緒加的鎖必須是同一把,都在裡面用Objict obj 就是new了兩把鎖,是不行的,就用我們外面的s就ok的。
問題3:雖然資料安全了,但是呢,一次一大片不好看,我就想依次的一次一個輸出
如何實現呢?
通過Java提供的等待換線機制解決
等待喚醒:
Object類中提供了3個方法:
wait():等待
notify():喚醒單個執行緒
notifyAll():喚醒所以執行緒
為什麼這些方法不定義在Thread類中呢?
這些方法的呼叫必須通過鎖物件呼叫,而外面房產使用的鎖物件是任意鎖物件,所以,這些方法必須定義在Object類中
*/
public class StudentDemo {
public static void main(String[] args) {
//建立資源
Student s=new Student();
SetThread st=new SetThread(s);
GetThread gt=new GetThread(s);
Thread t1=new Thread(st);
Thread t2=new Thread(gt);
t1.start();
t2.start();
}
}
package src;
public class Student {
private String name;
private int age;
boolean flag;//預設情況下是沒有資料,如果true,就說明有資料
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
package src;
public class SetThread implements Runnable {
private Student s;
private int x=0;
public SetThread(Student s ){
this.s=s;
}
@Override
public void run() {
while (true){
synchronized (s) {
//判斷有沒有
if(s.flag){
try {
s.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}//剛開始flag是flase,就不往if裡面走,然後開始生產
if (x % 2 == 0) {
s.setName("林青霞");
s.setAge(27);
} else {
s.setName("周志武");
s.setAge(18);
}
x++;
//修改標記
s.flag=true;
//喚醒執行緒
s.notify();
//一路走下來,如果有就修改標記,並喚醒執行緒
//喚醒t2,喚醒並不代表你馬上可以走,你還得搶cpu的執行權
//如何此時t1搶到了,進入if,開始wait方法,然後t2搶到,接著執行
//t2搶到,皆大歡喜。
}
}
// @Override
// public void run() {
// while (true){
// if(x%2==0) {
// s.setName("林青霞");
// s.setAge(27);
// }else {
// s.setName("周志武");
// s.setAge(18);
// }
// x++;
// }
}
}
package src;
public class GetThread implements Runnable {
private Student s;
public GetThread(Student s ){
this.s=s;
}
@Override
public void run() {
while (true) {
synchronized (s) {
if(!s.flag){
try {
s.wait();//真就等待,並釋放鎖(wait方法可以釋放),將來醒過來的時候,也是從這裡醒過來。
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(s.getName() + "---" + s.getAge());
//修改標記
s.flag=false;
//喚醒執行緒
s.notify();
}
}
}
// @Override
// public void run() {
// while (true) {
// System.out.println(s.getName() + "---" + s.getAge());
// }
// }
}
-18
林青霞—27
周志武—18
林青霞—27
周志武—18
林青霞—27
周志武—18
林青霞—27
周志武—18
林青霞—27
周志武—18
。。。
相關文章
- 6、JUC:傳統的生產者消費者問題,防止虛假喚醒問題
- Go基礎學習記錄之反射(reflect)機制Go反射
- 生產者與消費者之Android audioAndroid
- RocketMQ之消費者啟動與消費流程MQ
- 事件消費者之 Saga - 事件溯源事件
- 事件消費者之 Reactor - 事件溯源事件React
- 事件消費者之 Projector - 事件溯源事件Project
- 無鏡--kafka之消費者(四)Kafka
- 同步篇——事件等待與喚醒事件
- 群邑報告:消費者之眼
- 學習問題記錄:RocketMQ整合到SpringBoot後,消費者無法自動進行訊息消費。MQSpring Boot
- golang 併發程式設計之生產者消費者Golang程式設計
- ING報告:向消費者學習
- java多執行緒之消費生產模型-使用synchronized解決虛假喚醒Java執行緒模型synchronized
- 消費力量的覺醒:中國消費者的新購物觀
- Java併發之等待/通知機制Java
- javaSE綜合例項之記事本詳細解析--長篇(初學者)Java
- Redis學習之管道機制Redis
- 新手練習-消費者生產者模型模型
- 多執行緒之等待通知機制執行緒
- SpringCloud學習之路(四) - 服務消費者(Feign)SpringGCCloud
- RocketMQ原始碼解析之訊息消費者(consume Message)MQ原始碼
- 設計模式學習筆記之裝飾者模式設計模式筆記
- 生產者消費者
- C#多執行緒學習(三) 生產者和消費者C#執行緒
- 生產者消費者模式模式
- 生產者消費者模型模型
- Java安全之JDBC Attacks學習記錄JavaJDBC
- Dentsu:2022年消費者報告之COVID-19復甦
- Kafka 消費組消費者分配策略Kafka
- 開發者談遊戲設計師和玩家消費者之間的鴻溝遊戲設計師
- python 生產者消費者模式Python模式
- RocketMQ - 消費者概述MQ
- Kafka 消費者解析Kafka
- 凱度消費者指數:90後美妝消費者洞察
- 破解消費者密碼:線上消費者最重視什麼密碼
- Java 多執行緒學習(執行緒通訊——消費者和生產者)Java執行緒
- 向量資料庫之Lancedb學習記錄資料庫