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 }