1 package com.atguigu.thread.lock; 2 3 import java.util.concurrent.locks.Condition; 4 import java.util.concurrent.locks.Lock; 5 import java.util.concurrent.locks.ReentrantLock; 6 7 /* 8 * 小米厂家: 9 * 库房有限,只能存10台小米电视 10 * 工人的生产电视与销售的卖电视同时进行 11 * 当工人生产电视把库房存满了,要求工人休息,直到销售卖出至少一台电视,库房可以再次电视,然后他再次开始生产 12 * 当销售者把库房的电视都卖完了,要求销售者休息,直到工人生产了至少一台电视,销售才继续卖电视 13 * 14 * 工人是一个线程 15 * 销售是一个线程 16 * 17 * 需要线程的通信:当工人休息后,销售组销售了电视,应该告知工人一声,可以继续生产了 18 * 当销售休息后,工人如果生产了电视,应该通知销售,可以开始卖电视了 19 * 20 * 问题: 21 * (1)因为共享num变量,所以有线程安全问题:依靠同步解决 22 * (2)因为库房有限:线程通信 wait,notify 23 * 24 * 涉及到的方法: 25 * (1)wait:等待 26 * (2)notify/notifyAll:通知 27 * 28 * 这两个方法必须由“锁”对象来调用 29 * “锁”对象,必须是多个线程共享的锁对象 30 * 31 * 如果是多个工人,多个销售者 32 * 33 * synchronized:隐式锁 34 * wait 35 * notify/notifyAll 36 * 37 * 如果使用Lock锁,那么线程通信应该使用Condition来解决通信 38 * 条件.await():某种条件,等待 39 * 条件.signal():某种条件唤醒 40 * 41 */ 42 public class TestTongXin { 43 44 public static void main(String[] args) { 45 Houseware h = new Houseware(); 46 47 Worker w1 = new Worker(h); 48 Worker w2 = new Worker(h); 49 Saler s1 = new Saler(h); 50 Saler s2 = new Saler(h); 51 52 w1.start(); 53 w2.start(); 54 s1.start(); 55 s2.start(); 56 } 57 58 } 59 class Houseware{ 60 private static final int MAX_VALUE = 10; 61 private int num = 0; 62 private Lock lock = new ReentrantLock(); 63 private Condition full = lock.newCondition(); 64 private Condition empty = lock.newCondition(); 65 66 //往里放电视 67 public void add(){ 68 lock.lock(); 69 if(num>=MAX_VALUE){ 70 try { 71 full.await(); 72 } catch (InterruptedException e) { 73 e.printStackTrace(); 74 } 75 }else{ 76 num++; 77 try { 78 Thread.sleep(100);//为了问题暴露的明显一点 79 } catch (InterruptedException e) { 80 e.printStackTrace(); 81 } 82 System.out.println("工人生产了一台电视,现在库存是:" + num); 83 // empty.signal(); 84 empty.signalAll(); 85 } 86 87 lock.unlock(); 88 } 89 90 //往外拿电视 91 public void take(){ 92 lock.lock(); 93 if(num<=0){ 94 try { 95 empty.await(); 96 } catch (InterruptedException e) { 97 e.printStackTrace(); 98 } 99 }else{ 100 num--; 101 try { 102 Thread.sleep(100);//为了问题暴露的明显一点 103 } catch (InterruptedException e) { 104 e.printStackTrace(); 105 } 106 System.out.println("销售卖了一台电视,现在库存是:" + num); 107 full.signalAll(); 108 } 109 110 lock.unlock(); 111 } 112 } 113 114 class Worker extends Thread{ 115 private Houseware h; 116 117 public Worker(Houseware h) { 118 super(); 119 this.h = h; 120 } 121 122 public void run(){ 123 //往仓库放电视 124 // 库房.add(); 125 while(true){ 126 h.add(); 127 } 128 } 129 } 130 class Saler extends Thread{ 131 private Houseware h; 132 133 public Saler(Houseware h) { 134 super(); 135 this.h = h; 136 } 137 138 public void run(){ 139 while(true){ 140 h.take(); 141 } 142 } 143 }