补充知识:生产者和消费者模式
声明
版权声明:本文部分内容参考自CSDN博主「一个快乐的野指针~」的原创文章,仅用作个人学习,特此声明
原文链接: https://blog.csdn.net/qq_44715943/article/details/116714584
补充知识:生产者消费者模式(wait()和notify())
1、概念
- 生产线程负责生产,消费线程负责消费。
- 生产线程和消费线程要达到均衡。
- 这是一种特殊的业务需求,在这种特殊的情况下需要使用wait方法和notify方法。
2、模拟一个业务需求
模拟这样一个需求:
- 仓库我们采用List集合。
- List集合中假设只能存储1个元素。
- 1个元素就表示仓库满了。
- 如果List集合中元素个数是0,就表示仓库空了。
- 保证List集合中永远都是最多存储1个元素。
- 必须做到这种效果:生产1个消费1个。
3、设计思路
这种模式其实就是一种排队
因为只有生产出一个物品,才能消费;消费完这个物品,才能继续生产下一个物品。循环进行
也就是说wait方法和notify方法是建立在线程同步基础之上的,所以要考虑线程安全问题
eg.
使用wait方法和notify方法实现“生产者和消费者模式”
/**
* object类相关方法
* wait和notify方法测试
* 使用wait方法和notify方法实现"生产者和消费者模式"
* 两个线程其实是要排队的,生产完才能消费,消费完才能生产
* 所以wait方法和notify方法是建立在synchronized线程同步的基础之上的
*/
public class ThreadTest {
public static void main(String[] args) {
// 创建1个仓库对象,共享的。
List list = new ArrayList();
// 创建两个线程对象
// 生产者线程
Thread t1 = new Thread(new Producer(list));
// 消费者线程
Thread t2 = new Thread(new Consumer(list));
t1.setName("生产者线程");
t2.setName("消费者线程");
t1.start();
t2.start();
}
}
// 生产线程
class Producer implements Runnable {
// 仓库
private List list;
public Producer(List list) {
this.list = list;
}
@Override
public void run() {
// 一直生产(使用死循环来模拟一直生产)
while(true){
// 给仓库对象list加锁。
synchronized (list){
if(list.size() > 0){ // 大于0,说明仓库中已经有1个元素了。
try {
// 当前线程进入等待状态,并且释放Producer之前占有的list集合的锁。
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 程序能够执行到这里说明仓库是空的,可以生产
Object obj = new Object();
list.add(obj);
System.out.println(Thread.currentThread().getName() + "生产物品:" + obj);
// 唤醒消费者进行消费
list.notifyAll();
}
}
}
}
// 消费线程
class Consumer implements Runnable {
// 仓库
private List list;
public Consumer(List list) {
this.list = list;
}
@Override
public void run() {
// 一直消费
while(true){
synchronized (list) {
if(list.size() == 0){
try {
// 仓库已经空了。
// 消费者线程等待,释放掉list集合的锁
list.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 程序能够执行到此处说明仓库中有数据,进行消费。
Object obj = list.remove(0);//将集合中第0位元素移除,模拟将仓库中的唯一一个元素消费掉
System.out.println(Thread.currentThread().getName() + "消费物品:" + obj);
// 唤醒生产者生产。
list.notifyAll();
}
}
}
}
观察结果发现,生产者线程每生产一个物品,消费者线程就会把这个物品消费掉,消费掉之后才会继续生产,生产之后才能进行消费,达到了目的
4、知识点总结
-
两个线程其实是要排队的,生产完才能消费,消费完才能生产
所以wait方法和notify方法是建立在synchronized线程同步的基础之上的,需要考虑线程安全问题
-
o.wait() 方法让正在o对象上活动的线程t进入等待状态,并且释放掉t线程之前占有的o对象的锁。而o.notify() 方法会唤醒这o对象上等待的线程,只是通知,不会释放o对象上之前占有的锁。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律