小紅,女小紅,女小紅,女小紅,女小紅,女小紅,女小紅,女小紅,女小紅,女 出現以上結果??消費者一直消費或者生產者一直生產 解決方法:生產者生產完成後消費者方可消費,否者不可消費,消費者未消費或者未消費完生產者不可生產,一次生產一次消費。其實也就是保證對res共用資源的操作同一時刻僅有同一個線程進行 ...
class Res{ public String username; public String sex; } class Out extends Thread{ Res res; public Out(Res res){ this.res=res; } @Override public void run() { //寫操作 int count=0; while (true){ // synchronized (res.getClass()){ if(count==0){//偶數 res.username="小明"; res.sex="男"; } else {//奇數 res.username="小紅"; res.sex="女"; } count=(count+1)%2; // } } } } class Input extends Thread{ Res res; public Input(Res res){ this.res=res; } @Override public void run() { while (true){ // synchronized (res.getClass()){ System.out.println(res.username+","+res.sex); // } } } } public class OutInputThread { public static void main(String[] args) { Res res = new Res(); Out out = new Out(res); Input input = new Input(res); out.start(); input.start(); } }
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
小紅,女
出現以上結果??消費者一直消費或者生產者一直生產
解決方法:生產者生產完成後消費者方可消費,否者不可消費,消費者未消費或者未消費完生產者不可生產,一次生產一次消費。其實也就是保證對res共用資源的操作同一時刻僅有同一個線程進行操作,
wait、notify、notifyAll方法
wait、notify、notifyAll是三個定義在Object類里的方法,可以用來控制線程的狀態。
這三個方法最終調用的都是jvm級的native方法。隨著jvm運行平臺的不同可能有些許差異。
如果對象調用了wait方法就會使持有該對象的線程把該對象的控制權交出去,然後處於等待狀態。當前線程從運行變為阻塞,釋放所的資源
如果對象調用了notify方法就會通知某個正在等待這個對象的控制權的線程可以繼續運行。讓持有該鎖的線程從阻塞態變為就緒。
如果對象調用了notifyAll方法就會通知所有等待這個對象控制權的線程繼續運行。
註意:一定要線上程同步中使用,並且是同一個鎖的資源
通過以下方式即可完成需求。
生產者獲取res.getClass鎖後,如果flag為true生產者通過調用res.getClass.wait進行等待,此時其他線程可獲取該鎖,如果flag為false,進行生產,然後設置flag為true保證資源消費後方可再生產,接著通過notify通知其他喚醒其他線程。
class Res{ public String username; public String sex; //true 生產者等待,消費者可消費 false生產者可以生產,消費者不可消費 public boolean flag=false; } class Out extends Thread{ Res res; public Out(Res res){ this.res=res; } @Override public void run() { //寫操作 int count=0; while (true){ synchronized (res.getClass()){ if(res.flag){ try { res.getClass().wait();//讓當前線程從運行變為阻塞,並且釋放所的資源 } catch (InterruptedException e) { e.printStackTrace(); } } if(count==0){//偶數 res.username="小明"; res.sex="男"; } else {//奇數 res.username="小紅"; res.sex="女"; } count=(count+1)%2; res.flag=true; res.getClass().notify(); } } } } class Input extends Thread{ Res res; public Input(Res res){ this.res=res; } @Override public void run() { while (true){ synchronized (res.getClass()){ if(!res.flag){ try { res.getClass().wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(res.username+","+res.sex); res.flag=false; res.getClass().notify(); } } } } public class OutInputThread { public static void main(String[] args) { Res res = new Res(); Out out = new Out(res); Input input = new Input(res); out.start(); input.start(); } } 輸出如下: 小明,男 小紅,女 小明,男 小紅,女 小明,男 小紅,女 小明,男 小紅,女
如果去掉notify會怎樣?去掉一個?去掉兩個?
去掉一個生產者可以列印多個(但是也不多),去掉消費者僅可列印一個,去掉兩個可能不列印,也可能列印1個,所以wait、notify必須成對使用
wait(用於同步中)與sleep區別?
都是做休眠,wait需要notify
對於sleep方法,我們首先要知道該方法是屬於Thread類中的。而wait方法,則是屬於Object類中的。
sleep方法導致了程式暫停執行指定的時間,讓出cpu該其他線程,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢復運行狀態。
在調用sleep方法的過程中,線程不會釋放對象鎖。
而當調用wait方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify方法後本線程才進入對象鎖定池準備獲取對象鎖進入運行狀態。