线程间通信:一个线程向数据存储空间添加数据(唐老鸭),另一个线程从数据存储空间取出数据(米琪)。
程序有两种以外需要考虑:
1、 假设唐老鸭线程刚向数据存储空间添加了一辆车的名字。还没有加入这辆车的颜色,CPU就切换到了米琪线程,唐老鸭线程将把这辆车的名字和上辆车的颜色联系到了一起。
2 、唐老鸭了若干次的数据。米琪才开始取数据,或者是,米琪取完了一个数据后,还没等到唐老鸭放入新的数据,又重复取出已取过的数据。
可能出现的问题:
1唐老鸭比米琪快时,米琪会漏掉一些数据没有取到。
2、 米琪比唐老鸭快时,米琪取相同的数据。
多个线程共享同一资源的时候,必须进行同步,采用同步方法,解决第一个问题。
线程的等待和唤醒机制:
wait():告诉当前线程放弃监视器并进入睡眠状态,直到其他线程进入同一监视器并调用notify为止。
notify():唤醒同一对象监视器中调用wait的第一个线程。
程序中采用线程的等待和唤醒机制,当发现米琪没有取走内容时,唐老鸭应该等待,当米琪把内容取走之后,唐老鸭才可以放。这样解决了第二个问题。
代码如下:
package Killva.IOchaper4.o3;
class Animal{
private String name ="唐老鸭";
private String sex= "公";
private boolean flag=false;
public synchronized void set(String name, String sex){//生产者
//如果flag的值不是true则要等待
if(!flag){
//等待
try{
wait();
}catch(Exception e){}
}
//如果向下继续执行了,则表示可以设置, flag =true
this.name=name;
this.sex=sex;
//修改设置的标志
flag = false;
//唤醒其他线程
notify();
}
//设置一个输出的方法
public synchronized void get(){
//如果flag的值为true的时候,表示要等待
if(flag){
try{
wait();
}catch(Exception e){}
}
//如果向下执行了,就表示允许
System.out.println(this.name+"-->"+this.sex);
//改变标签
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();
}
}
运行结果:
感谢阅读 !!!欢迎交流!!! QQ:237333696