JAVA实现生产消费者模型
2024-08-29 00:55:05
前言
最近面试比较多,发现生产消费者模型在各公司面试的过程中问的还是比较多的,记录一下常见JAVA实现生产者消费模型的代码
思路
我们通过三种模式来实现
- 通过wait和notify
- 通过Lock和Condition
- 通过JAVA内部的阻塞队列ArrayBlockingQueue
代码
- wait和notify
通过synchronized来保证线程安全,在消息满或者不足的时候wait进行阻塞,然后notifyAll来通知其他监听
static class Storage {
private Queue<Integer> queue;
private Integer max;
public Storage(Queue<Integer> queue, Integer max) {
this.queue = queue;
this.max = max;
}
private synchronized void produce(Integer msg) {
while (queue.size() > max) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.offer(msg);
this.notifyAll();
}
private synchronized Integer consume() {
while (queue.size() == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Integer result = queue.poll();
this.notifyAll();
return result;
}
}
- Lock和Condition
通过Lock来保证线程安全,通过Condition来实现阻塞和通信,在消息队列满的时候,通过notFull的wait和notEmpty的signalAll来阻塞当前生产者并且通知消费者来消费消息,消息队列空的时候同理
static class Storage {
private Queue<Integer> queue;
private Integer max;
private Lock lock;
private Condition notEmpty;
private Condition notFull;
public Storage(Queue<Integer> queue, Integer max) {
this.queue = queue;
this.max = max;
lock = new ReentrantLock();
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
private void produce(Integer msg) {
lock.lock();
try {
while (queue.size() > max) {
notFull.await();
}
queue.offer(msg);
notEmpty.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
private synchronized Integer consume() {
lock.lock();
Integer result = null;
try {
while (queue.size() == 0) {
notEmpty.await();
}
result = queue.poll();
notFull.signalAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return result;
}
}
- 通过JAVA的实现类ArrayBlockingQueue
ArrayBlockingQueue是一个阻塞队列,在队列满的时候put会阻塞,空的时候take也会阻塞,其内部实现也是基于Lock和Condition来实现的
static class Storage {
private ArrayBlockingQueue<Integer> queue;
public Storage(Integer max) {
this.queue = new ArrayBlockingQueue<>(max);
}
private void produce(Integer msg) {
try {
queue.put(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private Integer consume() {
try {
return queue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
}
测试
生产线程:
static class Producer implements Runnable {
private Storage storage;
private Integer msg;
public Producer(Storage storage, Integer msg) {
this.storage = storage;
this.msg = msg;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
storage.produce(msg);
System.out.println("this is producer :" + msg);
}
}
}
消费者线程:
static class Consumer implements Runnable {
private Storage storage;
public Consumer(Storage storage) {
this.storage = storage;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("this is consumer:" + storage.consume());
}
}
}
测试用例:通过多个生产者消费者线程来模拟,执行代码后可验证生产和消费的有序进行
public static void main(String[] args) {
Storage storage = new Storage(2);
Producer producer = new Producer(storage, 1);
Producer producer2 = new Producer(storage, 2);
Producer producer3 = new Producer(storage, 3);
new Thread(producer).start();
new Thread(producer2).start();
new Thread(producer3).start();
Consumer consumer1 = new Consumer(storage);
Consumer consumer2 = new Consumer(storage);
Consumer consumer3 = new Consumer(storage);
new Thread(consumer1).start();
new Thread(consumer2).start();
new Thread(consumer3).start();
}
最新文章
- Easyui数据表格-地区列表及工具栏增删改
- C#不安全代码和stackalloc
- php无极分类
- js用斜率判断鼠标进入div的四个方向
- Linux磁盘管理:lvcreate 常用命令
- eclipse中如何导入jar包
- python之7-3对象的信息/方法获取
- fragement生命周期
- cordova 基本命令 以及如何添加,删除插件
- Spring Boot常用注解总结
- [Swift]LeetCode840. 矩阵中的幻方 | Magic Squares In Grid
- 解决No &#39;Access-Control-Allow-Origin&#39; header is present on the requested resource.跨域问题(后台(java)解决方法)
- 封装qq分享静态库到cocopod
- DeepLearning.ai-Week2-Residual Networks
- Django时区的解释
- Codeforces 1016G Appropriate Team 数论 FWT
- Sumo生成数据
- 范式及其在mysql数据库设计中的应用
- [C++]指针/指针数组/数组指针/多维指针/单值指针/多值指针
- uniGUI for C++ builder下如何利用FastReport实现数据记录本地打印
热门文章
- vue.config.js配置前端代理
- PHP7.1以上版本 count()报错
- 由于阿里云磁盘空间导致hadoop的yarn节点处于UNHEALTHY状态
- Spring解决循环依赖
- tcgetattr学习
- AcWing 227. 小部件厂 (高斯消元)打卡
- mysql启动脚本-my
- Android Studio遇到了“No USB devices or running emulators detected”
- Linux监控cpu,内存,磁盘脚本
- Oracle架构实现原理、含五大进程解析(图文详解)