從https://www.cnblogs.com/toov5/p/9837373.html 可以看到他的打印是一片一片的,這邊博客介紹怎么避免掉
使用notify 和 wait的時候 要注意 是在synchronize進行的,持有同一把鎖
1.因為涉及到對象鎖,他們必須都放在synchronized中來使用. Wait、Notify一定要在synchronized里面進行使用。
2.Wait必須暫定當前正在執行的線程,並釋放資源鎖,讓其他線程可以有機會運行
3. notify/notifyall: 喚醒因鎖池中的線程,使之運行
注意:一定要在線程同步中使用,並且是同一個鎖的資源
一片的原因是: cpu在調度時候 讀一直被調度上了
package com.toov5.thread; //共享對象 class Res{ public boolean flag = true; public String sex; public String name; } class inputThread extends Thread{ public Res res; public inputThread(Res res) { this.res=res; } @Override public void run() { int count=0; while (true) { synchronized (res) { if (res.flag) { try { res.wait(); //此處一定要用res的wait!!!! 執行到這里就會阻塞了 下面的代碼不會執行了 釋放當前鎖對象 } catch (InterruptedException e) { e.printStackTrace(); } } if (count==0) { res.name="lucy"; res.sex="girl"; }else { res.name="Jack"; res.sex="boy"; } count =(count+1)%2; res.flag=true; //寫完了 標記當前線程為等待 然后走wait()了 res.notify(); //通知讀的線程 } } } } class readThread extends Thread{ public Res res; public readThread(Res res) { this.res=res; } @Override public void run() { while (true) { synchronized (res) { if(!res.flag){ try { res.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(res.name+","+res.sex); //讀完了時候要 res.flag=false; res.notify();//通知寫的線程 } } } } public class ConmunicatThreadTest { //開啟兩個線程 下面的線程 主線程 還有這倆用戶線程 cpu隨機的 public static void main(String[] args) { Res res = new Res(); inputThread inputThread = new inputThread(res); readThread readThread = new readThread(res); inputThread.start(); readThread.start(); } }
看下結果:
分析下:
兩個線程 並行在執行 假設 flag為false 讀的線程會等待 cpu執行權讓給寫的線程同時鎖也會釋放掉
寫的時候 讀的線程發現為true (while(true)的情況) 等待notify() 被喚醒,被喚醒后 從wait處繼續往下執行 喚醒被等待的線程~~~
notifyall 是喚醒所有的 小伙伴們可以自己試試哈
注意 notify 和 wait 一定要在synchronize里面使用!!!!!並且同一個鎖對象的!
wait與join 區別:
wait需要喚醒 wait需要用在同步里面
wait與sleep區別
對於sleep()方法,我們首先要知道該方法是屬於Thread類中的。而wait()方法,則是屬於Object類中的。
sleep()方法導致了程序暫停執行指定的時間,讓出cpu該其他線程,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢復運行狀態。
在調用sleep()方法的過程中,線程不會釋放對象鎖。
而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法后本線程才進入對象鎖定池准備
獲取對象鎖進入運行狀態。
sleep不去釋放鎖 wait釋放
wait notify 為啥設計在object類 因為任意對象作為鎖嘛 Object是任何類的祖宗~ 所以小伙伴們都明了了吧~~