生产者-消费者模型
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
解决方法就是一个线程负责生产数据,放到共享区域,然后通知另一个线程去消耗数据。如果没有wait()和notify(),消费者线程就要不停去检查是否有数据被产生。
代码如下:
package produce_consume; import java.util.*; import java.util.List; import thread_test.test1; class Resource{ //生产上限 final int MAX = 10; List<String> list = new LinkedList<String>(); public synchronized void produce(){ while (list.size() > MAX) { System.out.println("生产过剩,等待消费"); try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } list.add("资源"); System.out.println("正在生产"); notify(); } public synchronized void consume(){ while (list.size() <= 0) { System.out.println("生产不足,等待生产"); try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } list.remove(0); System.out.println("正在消费"); notify(); } } class MyThread implements Runnable{ String name; Resource resource; public String getName() { return name; } public void setName(String name) { this.name = name; } public MyThread(String name,Resource resource){ this.name = name; this.resource = resource; } @Override public void run() { if (this.name.equals("生产者")) { resource.produce(); } if (this.name.equals("消费者")) { resource.consume(); } } } public class Test { public static void main(String[] args) { Resource resource = new Resource(); while (true) { Thread t1 = new Thread(new MyThread("消费者",resource)); t1.start(); Thread t2 = new Thread(new MyThread("生产者",resource)); t2.start(); } } }
需要注意的几点是
1. 要在synchronized的函数或对象里使用wait、notify和notifyAll,不然Java虚拟机会生成 IllegalMonitorStateException。
2. 要在while循环里而不是if语句下使用wait。这样,循环会在线程睡眠前后都检查wait的条件,并在条件实际上并未改变的情况下处理唤醒通知。
3. 要在多线程间共享的对象(在生产者消费者模型里即缓冲区队列)上使用wait。