前言

最近面试比较多,发现生产消费者模型在各公司面试的过程中问的还是比较多的,记录一下常见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. java中数据库和VO的一一对应关系

    如图所示,数据库中数据如果有下划线,则JavaVO中删除,除第一个单词外,其他单词首字母大写

  2. react 使用axios

    1.配置axios代理  使得axios  可以不写根路径 package.json "proxy":"http://localhost:4000", 2.使用 ...

  3. Anaconda 安装 pytorch报错解决方法

    一.安装Pytorch: # -c 指定用pytorch镜像源下载软件conda install pytorch torchvision cpuonly -c pytorch 报错: 二.配置: ch ...

  4. Linux运维学习网站收藏

    Linux运维之道 1>  http://www.linuxidc.com/      //Linux公社,收藏Linux学习的很多知识 2> http://http://www.jb51 ...

  5. AcWing 243. 一个简单的整数问题2 (树状数组)打卡

    题目:https://www.acwing.com/problem/content/244/ 题意:区间加,区间查询 思路:我们把原先那个差分数组分解一下 ∑i=1x∑j=1ib[j]=∑i=1x(x ...

  6. python 内置模块-re

    想要在python中使用正则表达式,就需要先导入re模块,正则表达式是一个强大的功能,可以为我们节省很多工作量. 一.元字符: 用一些具有特殊含义的符号表示特定种类的字符或位置.     . 匹配除换 ...

  7. Linux常用命令的使用方法

    Linux 命令大全 Linux 命令大全 1.文件管理 cat chattr chgrp chmod chown cksum cmp diff diffstat file find git gitv ...

  8. MySQL 5.7配置文件

    原文:http://www.voidcn.com/article/p-zrikccdi-hr.html # MySql5.7配置文件my.cnf设置[client]port = 3306socket ...

  9. Java 从入门到进阶之路(十七)

    在之前的文章我们介绍了一下 Java 中类的内部类,本章我们来看一下 Java 中的正则表达式. 在任何一种语言中,都绕不开正则表达式,而且大部分语言的正则表达式都有预定义的字符集,且预定义的字符集也 ...

  10. centos 7 下升级自带 sqlite3

    问题 在 centos 7 上面运行 django 2.2 开发服务器时出现: django.core.exceptions.ImproperlyConfigured: SQLite 3.8.3 or ...