线程间通信:一个线程向数据存储空间添加数据(Benz),另一个线程从数据存储空间取出数据(BMW)。
程序有两种以外需要考虑:
1、 假设Benz线程刚向数据存储空间添加了一辆车的名字。还没有加入这辆车的颜色,CPU就切换到了BMW线程,Benz线程将把这辆车的名字和上辆车的颜色联系到了一起。
2、 Benz放了若干次的数据。BMW才开始取数据,或者是,BMW取完了一个数据后,还没等到Benz放入新的数据,又重复取出已取过的数据。
可能出现的问题:
1、 Benz比BMW快时,BMW会漏掉一些数据没有取到。
2、 BMW比Benz快时,BMW取相同的数据。
多个线程共享同一资源的时候,必须进行同步,采用同步方法,解决第一个问题。
线程的等待和唤醒机制:
wait():告诉当前线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器并调用notify为止。
notify():唤醒同一对象监视器中调用wait的第一个线程。
程序中采用线程的等待和唤醒机制,当发现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){}
}
//如果向下继续执行了,则表示可以设置,flag=true
this.name=name;
this.color=color;
flag=false;
notify();
}
public synchronized void get(){
//如果flag的值为true的时候,表示要等待
if(flag){
try{
wait();
}catch(Exception e){}
}
//如果向下执行了,则表示允许取出
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();
}
}
运行结果: