1 package day2_4;
2
3 /**
4 * 线程通信的应用 经典例题: 生产者/消费者问题
5 * <p>
6 * 生产者(Productor)将产品交给店员(Clerk),而消费者(Consumer)从店员处取走产品,
7 * 店员一次只能持有固定数量范围的产品(比如 1-20个)
8 * 如果生产者试图生产更多的产品,店员会叫生产者停一下,等店中有空位放产品了再通知生产者继续生产。
9 * 如果店中没有产品了,店员会告诉消费者等一下,等店中有产品了再通知消费者来取走产品
10 * <p>
11 * 分析:
12 * 1.是否是多线程问题? 是 生产者线程、消费者线程
13 * 2.是否有共享数据? 是 店员(或产品)
14 * 3.如何解决线程的安全问题? 同步机制,有三种方法
15 * 4.是否涉及线程通信? 是
16 *
17 * @Author Tianhao
18 * @create 2021-02-05-23:42
19 */
20
21 //店员
22 class Clerk {
23 //产品数量
24 private int productCount;
25
26 public Clerk(int productCount) {
27 this.productCount = productCount;
28 }
29
30 //生产产品
31 public synchronized void produceProduct() {
32
33 if (productCount < 20) {
34 productCount++;
35 System.out.println(Thread.currentThread().getName() + "成产了第"
36 + productCount + "个产品");
37 //每生产了一个产品,就唤醒wait中的消费者
38 notify();
39
40 } else {
41 try {
42 //等待
43 wait();
44 } catch (InterruptedException e) {
45 e.printStackTrace();
46 }
47 }
48 }
49
50 //消费产品
51 public synchronized void customProduct() {
52 if (productCount > 0) {
53 System.out.println(Thread.currentThread().getName() + "消费了第"
54 + productCount + "个产品");
55 productCount--;
56 //每消费了一个产品,就唤醒正在wait的生产者
57 notify();
58 } else {
59 try {
60 //等待
61 wait();
62 } catch (InterruptedException e) {
63 e.printStackTrace();
64 }
65 }
66 }
67 }
68
69
70 //生产者
71 class Productor extends Thread{
72 private Clerk clerk;
73
74 public Productor(Clerk clerk) {
75 this.clerk = clerk;
76 }
77
78 @Override
79 public void run() {
80 System.out.println("生产者开始生产产品...");
81 while (true) {
82 try {
83 Thread.sleep(10);
84 } catch (InterruptedException e) {
85 e.printStackTrace();
86 }
87 clerk.produceProduct();
88 }
89 }
90 }
91
92 //消费者
93 class Consumer extends Thread{
94 private Clerk clerk;
95
96 public Consumer(Clerk clerk) {
97 this.clerk = clerk;
98 }
99
100 @Override
101 public void run() {
102 System.out.println("消费者开始消费产品...");
103 while (true) {
104 try {
105 Thread.sleep(20);
106 } catch (InterruptedException e) {
107 e.printStackTrace();
108 }
109 clerk.customProduct();
110 }
111 }
112 }
113
114 public class ProductTest {
115 public static void main(String[] args) {
116 Clerk clerk = new Clerk(0);
117 Productor p = new Productor(clerk);
118 Consumer c = new Consumer(clerk);
119 Consumer c2 = new Consumer(clerk);
120 p.setName("生产者1");
121 c.setName("消费者1");
122 c2.setName("消费者2");
123 p.start();
124 c.start();
125 c2.start();
126
127 }
128
129 }