class ProducerConsumer{ public static void main(String[] args){ Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t1 = new Thread(pro); Thread t2 = new Thread(con); t1.start(); t2.start(); } } class Resource{ private String name; private int count = 1; private boolean flag = false; public synchronized void set(String name){ if(flag) try{wait();}catch(Exception e){} this.name = name +"--"+count++; System.out.println(Thread.currentThread().getName()+ "-生产者-"+this.name); flag = true; this.notify(); } public synchronized void out(){ if(!flag) try{wait();}catch(Exception e){} System.out.println(Thread.currentThread().getName()+ "-消费者-"+this.name); flag = false; this.notify(); } } class Producer implements Runnable{ private Resource res; Producer(Resource res){ this.res = res; } public void run(){ while(true){ res.set("+商品+"); } } } class Consumer implements Runnable{ private Resource res; Consumer(Resource res){ this.res = res; } public void run(){ while(true){ res.out(); } } }
两个生产者两个消费者。改动如下。
class ProducerConsumer{ public static void main(String[] args){ Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t1 = new Thread(pro); Thread t2 = new Thread(pro); Thread t3 = new Thread(con); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } }
运行结果会出现另外两种情况:
1.生产者生成了两次,消费者只取一次
2.生产者生成一次,消费者取两次
发生这两种情况是因为没有判断标记flag。需要将if(flag)改为while(flag)。
但只修改这点,会导致所有进程都处于全部等待状态。所以要把notify()改为notifyAll();
但是改为notifyAll()唤醒的是所有线程,即同时包括生产者和消费者。改进方法见下一篇笔记。
/* 对于多个生产者和消费者 为什么要定义while判断标记? 原因:让被唤醒的线程再进行一次标记判断 为什么定义notifyAll()? 因为需要唤醒对方线程。用notify()容易出现唤醒 本方线程的情况,导致程序中的所有线程都等待。 */class ProducerConsumer{ public static void main(String[] args){ Resource r = new Resource(); Producer pro = new Producer(r); Consumer con = new Consumer(r); Thread t1 = new Thread(pro); Thread t2 = new Thread(pro); Thread t3 = new Thread(con); Thread t4 = new Thread(con); t1.start(); t2.start(); t3.start(); t4.start(); } } class Resource{ private String name; private int count = 1; private boolean flag = false; public synchronized void set(String name){ while(flag) try{wait();}catch(Exception e){} this.name = name +"--"+count++; System.out.println(Thread.currentThread().getName()+ "-生产者-"+this.name); flag = true; this.notifyAll(); } public synchronized void out(){ while(!flag) try{wait();}catch(Exception e){} System.out.println(Thread.currentThread().getName()+ "-消费者-"+this.name); flag = false; this.notifyAll(); } } class Producer implements Runnable{ private Resource res; Producer(Resource res){ this.res = res; } public void run(){ while(true){ res.set("+商品+"); } } } class Consumer implements Runnable{ private Resource res; Consumer(Resource res){ this.res = res; } public void run(){ while(true){ res.out(); } } }