管程法-生产者消费者问题

可参见:Java多线程笔记-2 | Whiskey&Cola (whiskeycola.cn)

在此为二次解释


管程法

  • 先得有一个缓冲区,这个缓冲区容量有限
  • 缓冲区定义存入,取出功能函数
  • 分别定义生产者、消费者类
  • 主程序,创建缓冲区,缓冲区当作参数,传入生产者消费者类的定义,创建线程

创建产品

1
2
3
4
5
6
7
8
class Product{
final String name = "laptop";
int id;

public Product(int id) {
this.id = id;
}
}

创建缓冲区

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
class Buffer{

final int bufferSize = 10;
// 创建一个容器,此容器可放10个产品
List<Product> productBuffer = new ArrayList<>();

// 放入容器函数,产品以参数形式传入
public synchronized void pushProduct(Product product){
// 如果容器满了,就先等待

while(productBuffer.size() >= bufferSize){
try{
this.wait();
}catch (Exception e){
System.out.println(e);
}
}
// 没有满,开始生产
productBuffer.add(product);
System.out.println("正在生产第" + product.id + "个" + product.name);

// 发出可以消费信号
this.notifyAll();
}

// 从容器取函数
public synchronized Product popProduct(){
// 如果容器没有值,就先等待
while(productBuffer.size() == 0){
try{
this.wait();
}catch(Exception e){
System.out.println(e);
}
}
// 容器有值,取一个
Product p = productBuffer.get(0);
productBuffer.remove(0);

// 发出可以生产信号
this.notifyAll();
return p;

}

}

创建生产者类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 创建生产者类
class Creater implements Runnable{
// 缓冲区及构造函数
Buffer buffer;

public Creater(Buffer buffer) {
this.buffer = buffer;
}

// 生产100个
@Override
public void run(){
for (int i = 0; i < 100; i++) {
buffer.pushProduct(new Product(i));
}
System.out.println("exit");
}

}

创建消费者类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 创建消费者线程
class Comsumer implements Runnable{

// 缓冲区和构造函数
Buffer buffer;

public Comsumer(Buffer buffer) {
this.buffer = buffer;
}

// 消费50个
@Override
public void run() {
for (int i = 0; i < 50; i++) {
Product product = buffer.popProduct();
System.out.println("消费第" + product.id + "个" + product.name);
}
}
}

主线程

1
2
3
4
5
6
7
8
9
10
11
12
// 主线程
public class CreaterComsumer {
public static void main(String[] args) {
Buffer buffer = new Buffer();
// 一个生产者,共生产100个
// 两个消费者,每人消费50个
new Thread(new Creater(buffer)).start();
new Thread(new Comsumer(buffer)).start();
new Thread(new Comsumer(buffer)).start();

}
}