前言

最近面试比较多,发现生产消费者模型在各公司面试的过程中问的还是比较多的,记录一下常见JAVA实现生产者消费模型的代码

思路

我们通过三种模式来实现

  1. 通过wait和notify
  2. 通过Lock和Condition
  3. 通过JAVA内部的阻塞队列ArrayBlockingQueue

代码

  1. 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;
}
}
  1. 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;
}
}
  1. 通过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();
}

最新文章

  1. Easyui数据表格-地区列表及工具栏增删改
  2. C#不安全代码和stackalloc
  3. php无极分类
  4. js用斜率判断鼠标进入div的四个方向
  5. Linux磁盘管理:lvcreate 常用命令
  6. eclipse中如何导入jar包
  7. python之7-3对象的信息/方法获取
  8. fragement生命周期
  9. cordova 基本命令 以及如何添加,删除插件
  10. Spring Boot常用注解总结
  11. [Swift]LeetCode840. 矩阵中的幻方 | Magic Squares In Grid
  12. 解决No &#39;Access-Control-Allow-Origin&#39; header is present on the requested resource.跨域问题(后台(java)解决方法)
  13. 封装qq分享静态库到cocopod
  14. DeepLearning.ai-Week2-Residual Networks
  15. Django时区的解释
  16. Codeforces 1016G Appropriate Team 数论 FWT
  17. Sumo生成数据
  18. 范式及其在mysql数据库设计中的应用
  19. [C++]指针/指针数组/数组指针/多维指针/单值指针/多值指针
  20. uniGUI for C++ builder下如何利用FastReport实现数据记录本地打印

热门文章

  1. vue.config.js配置前端代理
  2. PHP7.1以上版本 count()报错
  3. 由于阿里云磁盘空间导致hadoop的yarn节点处于UNHEALTHY状态
  4. Spring解决循环依赖
  5. tcgetattr学习
  6. AcWing 227. 小部件厂 (高斯消元)打卡
  7. mysql启动脚本-my
  8. Android Studio遇到了“No USB devices or running emulators detected”
  9. Linux监控cpu,内存,磁盘脚本
  10. Oracle架构实现原理、含五大进程解析(图文详解)