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 }