前言

最近面试比较多,发现生产消费者模型在各公司面试的过程中问的还是比较多的,记录一下常见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();
}

JAVA实现生产消费者模型的更多相关文章

  1. Java生产消费者模型——代码解析

    我们将生产者.消费者.库存.和调用线程的主函数分别写进四个类中,通过抢夺非线程安全的数据集合来直观的表达在进行生产消费者模型的过程中可能出现的问题与解决办法. 我们假设有一个生产者,两个消费者来共同抢 ...

  2. Linux——多线程下解决生产消费者模型

    我们学习了操作系统,想必对生产消费者问题都不陌生.作为同步互斥问题的一个经典案例,生产消费者模型其实是解决实际问题的基础模型,解决很多的实际问题都会依赖于它.而此模型要解决最大的问题便是同步与互斥.而 ...

  3. Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型

    Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义: ​ ​ ​ 每个对象都对应于一个可称为" 互斥锁&qu ...

  4. Python之queue模块以及生产消费者模型

    队列 队列类似于一条管道,元素先进先出,进put(arg),取get() 有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态. 队列分类 队列有很多中,但都依赖 ...

  5. Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁

    Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...

  6. Python - Asyncio模块实现的生产消费者模型

    [原创]转载请注明作者Johnthegreat和本文链接 在设计模式中,生产消费者模型占有非常重要的地位,这个模型在现实世界中也有很多有意思的对应场景,比如做包子的人和吃包子的人,当两者速度不匹配时, ...

  7. Java 实现生产者 – 消费者模型

    转自:http://www.importnew.com/27063.html 考查Java的并发编程时,手写“生产者-消费者模型”是一个经典问题.有如下几个考点: 对Java并发模型的理解 对Java ...

  8. Python——Queue模块以及生产消费者模型

    1.了解Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 |queue.Qu ...

  9. Java完成生产者消费者模型

    生产者和消费者模型,是多线程中的典型模型,这里使用Java完成该模型 ServerTest.java 生产者代码 package com.orange.threadmodel; import java ...

随机推荐

  1. 每天一个Linux命令:rm(5)

    rm rm命令可以删除一个目录中的一个或多个文件或目录,也可以将某个目录及其下属的所有文件及其子目录均删除掉.对于链接文件,只是删除整个链接文件,而原有文件保持不变 注意:使用rm命令要格外小心.因为 ...

  2. python--MySql 表记录的操作

    表记录的增删改查 ---插入表记录 全列插入:insert into 表名 values(...) 缺省插入:insert into 表名(列1,...) values(值1,...) -- 插入一条 ...

  3. Android中的ImageView的getDrawableCache获取背景图片的时候注意的问题

    获取ImageView的背景图片使用getDrawableCache方法,不要使用getDrawable方法,后者获取不到图片的. 1.在调用imageView.getDrawableCache()之 ...

  4. ubuntu Linux下chromium无法使用flash解决方法

    Chromium作为谷歌的开源浏览器将不再支持Netscape浏览器插件API,Adobe公司的Flash将无法正常工作了.然而用户可以使用Pepper Flash Player,这是谷歌浏览器上一款 ...

  5. Linux下Mysql安装与常见问题解决方案

    1.Mysql安装 环境: Mysql版本: 开始安装: 首先检查环境有没有老版本mysql,有的话先卸载干净,具体百度. 接着先获取mysql的安装包:wget https://dev.mysql. ...

  6. Eclipse ALT+/ 代码没有提示功能

    第一种配置如下: 第二: 第三: 以上三种方式是关于eclipse代码提示

  7. PHP生成PDF完美支持中文,解决TCPDF乱码

    PHP生成PDF完美支持中文,解决TCPDF乱码 2011-09-26 09:04 418人阅读 评论(0) 收藏 举报 phpfontsheaderttfxhtml文档 PHP生成PDF完美支持中文 ...

  8. Linux / Unix Command: rz

    yum install lrzsz Most communications programs invoke rz and sz automatically. You can also connect ...

  9. NetworkComms V3 序列化器之Protobuf.net和 JSONSerializer

    NetworkComms v3版本中,默认使用的是protobuf.net序列化器. 即当您没有指定序列化的时候,系统自动使用默认的protobuf.net序列化器. 当然我们也可以自己指定序列化器 ...

  10. Java中vector用法整理

    ArrayList会比Vector快,他是非同步的,如果设计涉及到多线程,还是用Vector比较好一些 import java.util.*; /** * 演示Vector的使用.包括Vector的创 ...