生产者-消费者模式Java实现

生产者-消费者是多线程协作中非常典型的例子!
主要是生产者负责生产产品,然后消费者进行消费,但是这样的模式有几个前提
①生产者在生产前必须判断消费者线程是否占用(这里用来了加锁机制来避免发生线程安全的问题,在某一时刻内只能有一个对象在占用线程),如果线程为空闲,则才生产产品,生产完成之后,再”唤醒”消费者进行强制消费,这里有点意思啊!
②消费者在消费时,同样也要判断是否线程空闲,如果占用就一起”等待“,否则就消费产品,完成后就”唤醒“生产者进行生产产品!

在这里插入图片描述

下面我们将上面的思路转换为代码实现一波:

首先我们要定义一个桌子类,类中应该包含产品的数量 ,锁对象,还有产品的是否可以食用的状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Desk {

//定义一个标记
//true 表示桌子上有汉堡,可以吃,否则就不可以
public static boolean flag = false;

//汉堡包的总数量
public static int count = 10;

//锁对象,只能是同一把锁
public static final Object lock = new Object();

}

然后就再定义生产者,这里的类定义为了Cooker,也是为为见名知意,Cooker类是一个线程,应该extends 线程类,然后重写run方法,写上生产的业务代码,也就是线程任务:

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
public class Cooker extends Thread {

//继承Thread必须实现run方法
@Override
public void run() {
while (true) {
//加的是同一把锁
synchronized (Desk.lock){
if (Desk.count == 0) {
break;
}else {
if (!Desk.flag) {
//生产
System.out.println("生产者正在生产产品....");
Desk.flag = true;
//叫醒消费者
Desk.lock.notifyAll();
}else {
//没有就等待
try {
Desk.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
}

然后就是消费者要进行消费了,线程任务和上面大致一样

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
public class Foodie extends Thread{

@Override
public void run() {
while (true) {
//加锁
synchronized (Desk.lock){
if (Desk.count == 0) {
break;
}else {
if (Desk.flag) {
//如果有
System.out.println("消费者正在消费....");
Desk.flag = false;
//唤醒生产者
Desk.lock.notifyAll();
Desk.count--;
}else {
//没有就等待
//使用什么对象当做锁,就必须用这个对象调用等待唤醒对象
try {
Desk.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
}

最后是主线程:

1
2
3
4
5
6
7
8
public static void main(String[] args) {

Foodie f = new Foodie();
Cooker c = new Cooker();

f.start();
c.start();
}

最后运行代码,看一下结果:
在这里插入图片描述

总结:

生产者-消费者模式主要是要对于多线程的应用场景下,要保证它的调度满足一定的规律!如有错误,请指正!