線程間通信:一個線程向數據存儲空間添加數據(Benz),另一個線程從數據存儲空間取出數據(BMW)。
程序有兩種以外需要考慮:
1、 假設Benz線程剛向數據存儲空間添加了一輛車的名字。還沒有加入這輛車的顏色,CPU就切換到了BMW線程,Benz線程將把這輛車的名字和上輛車的顏色聯系到了一起。
2、 Benz放了若干次的數據。BMW才開始取數據,或者是,BMW取完了一個數據后,還沒等到Benz放入新的數據,又重復取出已取過的數據。
可能出現的問題:
1、 Benz比BMW快時,BMW會漏掉一些數據沒有取到。
2、 BMW比Benz快時,BMW取相同的數據。
多個線程共享同一資源的時候,必須進行同步,采用同步方法,解決第一個問題。
線程的等待和喚醒機制:
wait():告訴當前線程放棄監(jiān)視器并進入睡眠狀態(tài),直到其他線程進入同一監(jiān)視器并調用notify為止。
notify():喚醒同一對象監(jiān)視器中調用wait的第一個線程。
程序中采用線程的等待和喚醒機制,當發(fā)現BMW沒有取走內容時,Benz應該等待,當BMW把內容取走之后,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í)行了,則表示可以設置,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);
//改變標志,表示可以生產了
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();
}
}
運行結果: