代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
* 生产者消费者问题
*/
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

public class MyTest {

private static int maxSize = 10;

public static void main(String[] args) {
// 存储数据
LinkedList<Integer> storage = new LinkedList<Integer>();

// 创建生产者消费者
Productor p1 = new Productor(storage, "1号生产者");
Productor p2 = new Productor(storage, "2号生产者");
Productor p3 = new Productor(storage, "3号生产者");
Consumer c1 = new Consumer(storage, "1号消费者");
Consumer c2 = new Consumer(storage, "2号消费者");
//Consumer c3 = new Consumer(storage, "3号消费者");

// 创建线程
Thread t1 = new Thread(p1);
Thread t2 = new Thread(p2);
Thread t3 = new Thread(p3);
Thread t4 = new Thread(c1);
Thread t5 = new Thread(c2);
//Thread t6 = new Thread(c3);

// 开启线程
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
//t6.start();
}

/*
* 生产者类
*/
static class Productor implements Runnable {
private String name;
private List<Integer> list;

private Productor(List<Integer> list, String name) {
this.list = list;
this.name = name;
}

@Override
public void run() {
while (true) {
synchronized (list) {
while (list.size() >= maxSize) {
System.out.println(name + "因空间不足,无法生产,进入等待");
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 这里也可以随机生成一个数字当成是商品
list.add(1);
System.out.println(name + "生产了1个商品,现库存:" + list.size());

// 生产完成后唤醒所有等待线程
list.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

/*
* 消费者类
*/
static class Consumer implements Runnable {
private String name;
private List<Integer> list;

private Consumer(List<Integer> list, String name) {
this.list = list;
this.name = name;
}

@Override
public void run() {
while (true) {
synchronized (list) {
while (list.size() == 0) {
System.out.println(name + "因余量不足,无法消费,进入等待队列");
try {
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 删除list的第一个元素
list.remove(0);
System.out.println(name + "消费了一个商品,现库存:" + list.size());

// 消费完成后唤醒所有的线程
list.notifyAll();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

}

}

代码中创建了 3 个生产者,2 个消费者,一直进行生产/消费行为。

并且设置仓储的最大容量为 10。

运行结果如下:

1号生产者生产了1个商品,现库存:1
2号生产者生产了1个商品,现库存:2
2号消费者消费了一个商品,现库存:1
3号生产者生产了1个商品,现库存:2
1号消费者消费了一个商品,现库存:1
2号生产者生产了1个商品,现库存:2
1号生产者生产了1个商品,现库存:3
1号消费者消费了一个商品,现库存:2
2号消费者消费了一个商品,现库存:1
3号生产者生产了1个商品,现库存:2
1号生产者生产了1个商品,现库存:3
2号生产者生产了1个商品,现库存:4
3号生产者生产了1个商品,现库存:5
1号消费者消费了一个商品,现库存:4
2号消费者消费了一个商品,现库存:3
1号生产者生产了1个商品,现库存:4
2号生产者生产了1个商品,现库存:5
2号消费者消费了一个商品,现库存:4
3号生产者生产了1个商品,现库存:5
1号消费者消费了一个商品,现库存:4
1号生产者生产了1个商品,现库存:5
2号生产者生产了1个商品,现库存:6
2号消费者消费了一个商品,现库存:5
3号生产者生产了1个商品,现库存:6
1号消费者消费了一个商品,现库存:5
2号生产者生产了1个商品,现库存:6
1号生产者生产了1个商品,现库存:7
1号消费者消费了一个商品,现库存:6
3号生产者生产了1个商品,现库存:7
2号消费者消费了一个商品,现库存:6
2号生产者生产了1个商品,现库存:7
1号生产者生产了1个商品,现库存:8
2号消费者消费了一个商品,现库存:7
3号生产者生产了1个商品,现库存:8
1号消费者消费了一个商品,现库存:7
2号生产者生产了1个商品,现库存:8
1号生产者生产了1个商品,现库存:9
3号生产者生产了1个商品,现库存:10
2号消费者消费了一个商品,现库存:9
1号消费者消费了一个商品,现库存:8
2号生产者生产了1个商品,现库存:9
1号生产者生产了1个商品,现库存:10
2号消费者消费了一个商品,现库存:9
3号生产者生产了1个商品,现库存:10
1号消费者消费了一个商品,现库存:9
2号生产者生产了1个商品,现库存:10
1号生产者因空间不足,无法生产,进入等待
3号生产者因空间不足,无法生产,进入等待
2号消费者消费了一个商品,现库存:9
1号消费者消费了一个商品,现库存:8
3号生产者生产了1个商品,现库存:9
1号生产者生产了1个商品,现库存:10
2号生产者因空间不足,无法生产,进入等待
1号消费者消费了一个商品,现库存:9
2号生产者生产了1个商品,现库存:10
3号生产者因空间不足,无法生产,进入等待
1号生产者因空间不足,无法生产,进入等待
2号消费者消费了一个商品,现库存:9
1号生产者生产了1个商品,现库存:10
3号生产者因空间不足,无法生产,进入等待
……

注意点

1、wait 外面一般要套用一个 while (条件判断)
如果不加,那么notify过早,线程会陷入等待;如果用 if(条件判断),那么线程在判断条件后,进入等待;这时条件已经被更改,该线程被唤醒后会继续执行,而不会重新判断是否符合现在的条件。
2、应使用 notifyAll 而不是 notify
如果仓储已满,而被唤醒的一直是生产者,那么所有线程都将陷入等待。

Reference

https://www.jianshu.com/p/e29632593057