持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第16天,点击查看活动详情
大家好,我是尚影嫣🌷,一名Java后端程序媛。如果您喜欢我的文章,欢迎点赞➕关注❤️,让我们一起成为更好的我们~🥰
所谓生产者消费者模式,即多个线程进行生产,同时多个线程进行消费。两种角色通过内存缓冲区进行通信,解决了代码之间的耦合程度。
信号灯法
使用Object的wait() / notify()方法:
wait() / nofity()方法是基类Object的两个方法,所以所有的Java类都拥有这两个方法,我们就可以为任何对象实现同步机制。
-
wait():当缓冲区已满/空时,生产者/消费者线程停止自己的执行,放弃锁,使自己处于等待状态,让其他线程执行。
-
notify():当生产者/消费者向缓冲区放入/取出一个产品时,向其他等待的线程发出可执行的通知,同时放弃锁,使自己处于等待状态。
package yanf.thread;
public class ProducerAndConsumer {
public static void main(String[] args) {
Food f = new Food();
new Cooker(f).start();
new Waiter(f).start();
}
// 生产者-厨师
static class Cooker extends Thread {
private Food f;
public Cooker(Food f) {
this.f = f;
}
// 做菜
@Override
public void run() {
for (int i = 0; i < 100; i++) {
if (i % 2 == 0) {
f.setNameAndTaste("小米南瓜粥", "清香~");
} else {
f.setNameAndTaste("奶油小蛋糕", "甜甜腻腻!");
}
}
}
}
// 消费者-服务员
static class Waiter extends Thread {
private Food f;
public Waiter(Food f) {
this.f = f;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
// 休眠0.1s
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 端菜
f.get();
}
}
}
// 食物
static class Food {
private String name;
private String taste;
// true 表示可以生产
private boolean flag = true;
public synchronized void setNameAndTaste(String name, String taste) {
if (flag) {
this.name = name;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.taste = taste;
flag = false;
// 唤醒其他休息的线程
this.notifyAll();
// 休息一下
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void get() {
if (!flag) {
System.out.println("服务员端走的菜的名称是:" + name + ",味道是:" + taste);
flag = true;
this.notifyAll();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
运行结果如下: