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