線程間通信:一個線程向數(shù)據(jù)存儲空間添加數(shù)據(jù)(唐老鴨),另一個線程從數(shù)據(jù)存儲空間取出數(shù)據(jù)(米琪)。
程序有兩種以外需要考慮:
1、 假設(shè)唐老鴨線程剛向數(shù)據(jù)存儲空間添加了一輛車的名字。還沒有加入這輛車的顏色,CPU就切換到了米琪線程,唐老鴨線程將把這輛車的名字和上輛車的顏色聯(lián)系到了一起。
2 、唐老鴨了若干次的數(shù)據(jù)。米琪才開始取數(shù)據(jù),或者是,米琪取完了一個數(shù)據(jù)后,還沒等到唐老鴨放入新的數(shù)據(jù),又重復(fù)取出已取過的數(shù)據(jù)。
可能出現(xiàn)的問題:
1唐老鴨比米琪快時,米琪會漏掉一些數(shù)據(jù)沒有取到。
2、 米琪比唐老鴨快時,米琪取相同的數(shù)據(jù)。
多個線程共享同一資源的時候,必須進行同步,采用同步方法,解決第一個問題。
線程的等待和喚醒機制:
wait():告訴當(dāng)前線程放棄監(jiān)視器并進入睡眠狀態(tài),直到其他線程進入同一監(jiān)視器并調(diào)用notify為止。
notify():喚醒同一對象監(jiān)視器中調(diào)用wait的第一個線程。
程序中采用線程的等待和喚醒機制,當(dāng)發(fā)現(xiàn)米琪沒有取走內(nèi)容時,唐老鴨應(yīng)該等待,當(dāng)米琪把內(nèi)容取走之后,唐老鴨才可以放。這樣解決了第二個問題。
代碼如下:
package Killva.IOchaper4.o3;
class Animal{
private String name ="唐老鴨";
private String sex= "公";
private boolean flag=false;
public synchronized void set(String name, String sex){//生產(chǎn)者
//如果flag的值不是true則要等待
if(!flag){
//等待
try{
wait();
}catch(Exception e){}
}
//如果向下繼續(xù)執(zhí)行了,則表示可以設(shè)置, flag =true
this.name=name;
this.sex=sex;
//修改設(shè)置的標(biāo)志
flag = false;
//喚醒其他線程
notify();
}
//設(shè)置一個輸出的方法
public synchronized void get(){
//如果flag的值為true的時候,表示要等待
if(flag){
try{
wait();
}catch(Exception e){}
}
//如果向下執(zhí)行了,就表示允許
System.out.println(this.name+"-->"+this.sex);
//改變標(biāo)簽
flag =true;
notify();
}
}
class Pro implements Runnable{
Animal per =null;
public Pro(Animal p){
this.per=p;
}
public void run() {
int i =0;
while (true){
if(i==0){
per.set("米琪", "母");
i=1;
}else{
per.set("唐老鴨", "公");
i=0;
}
}
}
}
class Cus implements Runnable{
Animal per =null;
public Cus(Animal p){
this.per=p;
}
public void run() {
while(true){
per.get();
}
}
}
public class Demo01 {
//主方法
public static void main(String[] args){
Animal per =new Animal();
Pro p =new Pro(per);
Cus c =new Cus(per);
new Thread(p).start();
new Thread(c).start();
}
}
運行結(jié)果:
感謝閱讀 !!!歡迎交流!!! QQ:237333696