7.生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信)
1 /* 2 * 生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信) 3 * */ 4 public class TestProductorAndConsumerForLock { 5 public static void main(String[] args) { 6 WareHouse wareHouse = new WareHouse(); 7 Productor pd1 = new Productor(wareHouse); 8 Consumer cs1 = new Consumer(wareHouse); 9 10 new Thread(pd1, "消费者1").start(); 11 new Thread(cs1, "生产者1").start(); 12 // 若有多个 生产者消费者,可能会产生虚假唤醒(缺货了,多个生产线程等待,唤醒时,这些生产线程同时醒来,对数据进行操作,这种问题叫做虚假唤醒) 13 // 解决办法:wait方法 尽量 使用在循环中,被唤醒之后,再去判断是否符合条件(库存是否达到上限),不符合条件 14 // 继续等待(等待消费者去消费商品),直到 条件符合(库存有空闲) 15 new Thread(pd1, "消费者2").start(); 16 new Thread(cs1, "生产者2").start(); 17 } 18 } 19 20 // 仓库 21 class WareHouse { 22 // 商品数量 23 private int products = 0; 24 private ReentrantLock lock = new ReentrantLock(); 25 //使用 Condition 的前提是 使用 Lock 同步锁,Condition 实例 实质上被绑定到一个锁上 26 private Condition condition = lock.newCondition(); 27 28 public void set() { 29 lock.lock(); 30 try { 31 while (products >= 1) { 32 System.out.println("商品库存满了"); 33 try { 34 // 如果商品满了,阻塞线程,等待消费者线程消费完成后唤醒, 35 condition.await(); //相当于(Object.awatit() 但是功能更强大) 36 } catch (InterruptedException e) { 37 // TODO Auto-generated catch block 38 e.printStackTrace(); 39 } 40 } 41 System.out.println("生产了商品,剩余库存" + ++products); 42 condition.signalAll(); //相当于 (Object.notifyAll,功能更强大) 43 } finally { 44 lock.unlock(); 45 } 46 47 } 48 49 public void get() { 50 lock.lock(); 51 try { 52 while (products <= 0) { 53 System.out.println("商品库存没了"); 54 try { 55 // 如果商品没了,阻塞线程,等待生产者线程生产完成后唤醒, 56 condition.await(); 57 } catch (InterruptedException e) { 58 // TODO Auto-generated catch block 59 e.printStackTrace(); 60 } 61 } 62 System.out.println("消费了商品,剩余库存" + --products); 63 condition.signalAll(); 64 } finally { 65 lock.unlock(); 66 } 67 68 } 69 } 70 71 // 生产者 72 class Productor implements Runnable { 73 private WareHouse wareHouse; 74 75 public Productor(WareHouse wareHouse) { 76 this.wareHouse = wareHouse; 77 } 78 79 @Override 80 public void run() { 81 for (int i = 0; i < 20; i++) { 82 try { 83 Thread.sleep(200); 84 } catch (InterruptedException e) { 85 // TODO Auto-generated catch block 86 e.printStackTrace(); 87 } 88 wareHouse.get(); 89 } 90 } 91 92 } 93 94 // 消费者 95 class Consumer implements Runnable { 96 private WareHouse wareHouse; 97 98 public Consumer(WareHouse wareHouse) { 99 this.wareHouse = wareHouse; 100 } 101 102 @Override 103 public void run() { 104 for (int i = 0; i < 20; i++) { 105 106 wareHouse.set(); 107 } 108 } 109 110 }