Java多线程10-生产者消费者问题
1、生产/消费者模型
生产/消费者模型是一个典型的多线程问题,涉及到的对象包括“生产者”、“消费者”、“仓库”和“产品”。它们之间的关系如下;
(01)生产者仅仅在仓库未满的时候生产,仓库满了则停止生产
(02)消费者仅仅在仓库有产品的时候才能消费,仓库空则等待
(03)当消费者发现仓库没有产品的时候会通知生产者生产
(04)生产者在生产出可消费的产品时,应该通知等待的消费者去消费
2、实现
class Depot { private int capacity; //仓库容量 private int size; //仓库的实际数量 public Depot(int capacity) { this.capacity = capacity; this.size = 0; } public synchronized void produce(int val) { try { int left = val; //表示想要生产的数量 while(left > 0) { while(size >= capacity) //仓库满了,等待消费者 wait(); //计算实际增量 //如果库存+想要生产的数量 > 容量,则“实际增量” = “容量” - “当前容量”(这样会填满仓库) //否则,增量 = 想要生产的数量 int increment = (size+left) > capacity ? (capacity-size) : left; size = size + increment; left = left - increment; System.out.printf("%S produce(%d) --> left = %d,inc = %d, size = %d\n", Thread.currentThread().getName(),val,left,increment,size); notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } public synchronized void consume(int val) { try { int left = val; while(left > 0) { while(size <= 0) wait(); int decrement = size < left ? size : left; size = size - decrement; left = left - decrement; System.out.printf("%s consume(%d) <-- left = %d, dec = %d, size = %d\n", Thread.currentThread().getName(),val,left,decrement,size); notifyAll(); } } catch (InterruptedException e) { e.printStackTrace(); } } public String toString() { return "capacity:"+capacity+", actual size:"+size; } } class Customer { private Depot depot; public Customer(Depot depot) { this.depot = depot; } public void consume(final int val) { new Thread() { public void run() { depot.consume(val); } }.start(); } } class Producer { private Depot depot; public Producer(Depot depot) { this.depot = depot; } public void produce(final int val) { new Thread() { public void run() { depot.produce(val); } }.start(); } } public class Demo { public static void main(String[] args) { Depot mDepot = new Depot(100); Producer mPro = new Producer(mDepot); Customer mCus = new Customer(mDepot); mPro.produce(60);; mPro.produce(120); mCus.consume(90); mCus.consume(150); mPro.produce(110); } }
运行结果:
THREAD-0 produce(60) --> left = 0,inc = 60, size = 60 THREAD-4 produce(110) --> left = 70,inc = 40, size = 100 Thread-3 consume(150) <-- left = 50, dec = 100, size = 0 THREAD-1 produce(120) --> left = 20,inc = 100, size = 100 Thread-2 consume(90) <-- left = 0, dec = 90, size = 10 Thread-3 consume(150) <-- left = 40, dec = 10, size = 0 THREAD-4 produce(110) --> left = 0,inc = 70, size = 70 Thread-3 consume(150) <-- left = 0, dec = 40, size = 30 THREAD-1 produce(120) --> left = 0,inc = 20, size = 50
五个线程都把自己想生产或者想消费的执行完毕