JAVA实现生产消费者模型
前言
最近面试比较多,发现生产消费者模型在各公司面试的过程中问的还是比较多的,记录一下常见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();
}
JAVA实现生产消费者模型的更多相关文章
- Java生产消费者模型——代码解析
我们将生产者.消费者.库存.和调用线程的主函数分别写进四个类中,通过抢夺非线程安全的数据集合来直观的表达在进行生产消费者模型的过程中可能出现的问题与解决办法. 我们假设有一个生产者,两个消费者来共同抢 ...
- Linux——多线程下解决生产消费者模型
我们学习了操作系统,想必对生产消费者问题都不陌生.作为同步互斥问题的一个经典案例,生产消费者模型其实是解决实际问题的基础模型,解决很多的实际问题都会依赖于它.而此模型要解决最大的问题便是同步与互斥.而 ...
- Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型
Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义: 每个对象都对应于一个可称为" 互斥锁&qu ...
- Python之queue模块以及生产消费者模型
队列 队列类似于一条管道,元素先进先出,进put(arg),取get() 有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态. 队列分类 队列有很多中,但都依赖 ...
- Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁
Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...
- Python - Asyncio模块实现的生产消费者模型
[原创]转载请注明作者Johnthegreat和本文链接 在设计模式中,生产消费者模型占有非常重要的地位,这个模型在现实世界中也有很多有意思的对应场景,比如做包子的人和吃包子的人,当两者速度不匹配时, ...
- Java 实现生产者 – 消费者模型
转自:http://www.importnew.com/27063.html 考查Java的并发编程时,手写“生产者-消费者模型”是一个经典问题.有如下几个考点: 对Java并发模型的理解 对Java ...
- Python——Queue模块以及生产消费者模型
1.了解Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 |queue.Qu ...
- Java完成生产者消费者模型
生产者和消费者模型,是多线程中的典型模型,这里使用Java完成该模型 ServerTest.java 生产者代码 package com.orange.threadmodel; import java ...
随机推荐
- 【串线篇】mybatis-config.xml配置事项
一.术语 properties 属性 settings 设置 typeAliases 类型命名 typeHandlers 类型处理器 objectFactory 对象工厂, plugins 插件, e ...
- hibernate简单连接mysql数据库配置
使用hibernate连接mysql数据库 1:项目搭建好之后,在lib包中添加必要的jar包,和mysql数据库驱动jar包: jar包可以在hibernate的下载包(hibernate3.3.2 ...
- Ubuntu下的安装notepad++
Ubuntu下的安装方法: sudo add-apt-repository ppa:notepadqq-team/notepadqq sudo apt-get update sudo apt-get ...
- MariaDB 安装
MariaDB的所有下载都位于官方MariaDB基金会网站的下载部分. 单击所需版本的链接,并显示多个操作系统,体系结构和安装文件类型的下载列表. 在LINUX / UNIX上安装 如果你熟悉Linu ...
- NVMe SSD是什么?
https://blog.51cto.com/alanwu/1766945 一直对闪存存储关注的朋友对NVMe SSD一定非常熟悉,NVMe SSD是现如今性能最好的存储盘.这种高性能盘在互联网领域已 ...
- Adobe 2019 全家桶 Win 版
Adobe Creative Cloud 2019 4月版已更新一段时间了,为了让广大Adobe的发烧友能够第一时间体验最新的产品,happy特意为大家收集到了最新的 Adobe CC 2019 全套 ...
- Mysql忘记密码:关于ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' (using password: NO)的问题
命令行登录mysql时,出现ERROR 1045 (28000): Access denied for user 'ODBC'@'localhost' (using password: NO)的提示. ...
- kvm无人值守安装centos6
nginx配置 server { listen default_server; server_name _; root /home/iso; # Load configuration files fo ...
- websocket 文件上传
<template> <div class="pad20"> <input id="file" ref="f ...
- Appium+python自动化-查看app元素属性
本文转自:https://www.cnblogs.com/yoyoketang/p/7581831.html 前言 学UI自动化首先就是定位页面元素,玩过android版的appium小伙伴应该都知道 ...