生产和消费者模式有很多种,现在介绍几种常见的方式

  •   wait/notify实现生产和消费者模式

1、使用wait/notify实现生产和消费者模式:

public class Depot {

    // 实际容量
private volatile int capacity = 0 ;
// 最大容量
private static final int MAX_CAPACITY = 100 ;
// 锁
private final Object lock = new Object() ; public Depot(){ } /**
* 生产
* @param: num
* @return:
*/
public void producer(int num) {
if(num<0){
System.out.println("生产数量不可为负数");
throw new IllegalArgumentException("生产数量不可为负数") ;
} synchronized (lock){
// 生产
int left = 0;
try {
left = doProducer(num); // 要求生产数量未达标,让出执行权
while (left > 0){
Thread.yield();
left = doProducer(left);
}
} catch (InterruptedException e) {
e.printStackTrace();
} lock.notify();
} } /**
* 实际生产逻辑
* @param: num
* @return: 返回未生产数量
*/
private int doProducer(int num) throws InterruptedException {
// 实际增加数量
int grow = num ;
// 未生产数量
int left = 0 ; // 等待仓库被消费
while (capacity>=MAX_CAPACITY){
lock.wait();
} // 计算实际新增数量
if( (num+capacity) > MAX_CAPACITY ){
grow = MAX_CAPACITY - capacity ;
left = num - grow ;
}
capacity += grow ; // 仓库已经生产,通知消费者消费
lock.notify();
System.out.println(Thread.currentThread().getName() + " Plan Producer = " + num + " Actually = " + grow + " left = " + left + " capacity = " + capacity);
return left ;
} /**
* 消费
* @param: num
* @return:
*/
public void consumer(int num) {
if(num<0){
System.out.println("消费数量不可为负数");
throw new IllegalArgumentException("消费数量不可为负数") ;
} synchronized (lock){
// 消费仓库
int left = 0;
try {
left = doConsumer(num); // 要求消费数量未达标,让出执行权
while (left > 0){
Thread.yield();
left = doConsumer(left);
}
} catch (InterruptedException e) {
e.printStackTrace();
} // 仓库已经被消费,通知生产者生产
lock.notify();
} } /**
* 实际消费逻辑
* @param: num
* @return: 剩余未消费数量
*/
private int doConsumer(int num) throws InterruptedException {
// 实际消费数量
int decrease = num ;
// 剩余未消费
int left = 0 ; // 等待仓库生产
while (capacity <= 0){
lock.wait();
} // 计算实际消费数量
if(decrease > capacity){
decrease = capacity ;
left = decrease - capacity ;
}
capacity -= decrease ; System.out.println(Thread.currentThread().getName() + " Plan Consumer = "+ num + " Actually = " + decrease + " left = " + left + " capacity = " + capacity );
return left ;
} }

测试案例:

public class ProducerAndConsumer {
public static void main(String[] args) throws InterruptedException {
Depot depot = new Depot() ; for(int x=0 ; x<4; x++){
new Thread(new Runnable() {
@Override public void run() {
depot.producer(40);
}
}).start();
} Thread.sleep(2000L);
for(int x=0 ; x<3; x++){
new Thread(new Runnable() {
@Override public void run() {
depot.consumer(40);
}
}).start();
} Thread.sleep(2000L); }
}

运行结果:

Thread-0 Plan Producer = 40 Actually = 40 left =  0  capacity = 40
Thread-1 Plan Producer = 40 Actually = 40 left = 0 capacity = 80
Thread-2 Plan Producer = 40 Actually = 20 left = 20 capacity = 100
Thread-4 Plan Consumer = 40 Actually = 40 left = 0 capacity = 60
Thread-2 Plan Producer = 20 Actually = 20 left = 0 capacity = 80
Thread-3 Plan Producer = 40 Actually = 20 left = 20 capacity = 100
Thread-6 Plan Consumer = 40 Actually = 40 left = 0 capacity = 60
Thread-5 Plan Consumer = 40 Actually = 40 left = 0 capacity = 20
Thread-3 Plan Producer = 20 Actually = 20 left = 0 capacity = 40

其他待续.........

java 实现生产者-消费者模式的更多相关文章

  1. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  2. java多线程 生产者消费者模式

    package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...

  3. 关于java中生产者消费者模式的理解

    在说生产者消费者模式之前,我觉得有必要理解一下 Obj.wait(),与Obj.notify()方法.wait()方法是指在持有对象锁的线程调用此方法时,会释放对象锁,同时休眠本线程.notify() ...

  4. java实现生产者消费者模式

    生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将 ...

  5. java——利用生产者消费者模式思想实现简易版handler机制

    参考教程:http://www.sohu.com/a/237792762_659256 首先说一下这里面涉及到的线程: 1.mainLooper: 这个线程可以理解为消费者线程,里面运行了一个死循环, ...

  6. java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】

    java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...

  7. Java 生产者消费者模式详细分析

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  8. java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比

    package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...

  9. Java 学习笔记 使用并发包ReentrantLock简化生产者消费者模式代码

    说明 ReentrantLock是java官方的一个线程锁类,ReentarntLock实现了Lock的接口 我们只需要使用这个,就可以不用使用synchronized同步关键字以及对应的notify ...

随机推荐

  1. 蓝桥杯 大臣的旅费_树的最长度_两次DFS

    #include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> ...

  2. go语言学习之路(一)Hello World

    为什么要使用 Go 语言?Go 语言的优势在哪里? 1.部署简单. 2.并发性好. 3.良好的语言设计. 4.执行性能好. Go环境搭建 Golang下载 国外镜像  https://www.gola ...

  3. [转载]AngularJS 指令 用法

    http://book.2cto.com/201312/37782.html http://www.itnose.net/detail/6144038.html http://www.cnblogs. ...

  4. 利用fiddler来模拟低速环境

    为了让我们的站点拥有更好的用户体验,更短的加载时间,我们会“按需加载”页面的资源. 在调试程序的时候,我们希望能有一个低速率的网络环境来模拟真实线上的环境,这个时候fiddler(下载fiddler请 ...

  5. xmlhttprequest upload

    html5 带进度上传 function fileSelected() { var file = document.getElementById('fileToUpload').files[0]; i ...

  6. RabbitMq简单应用

    服务端: <?php //配置信息 $conn_args = array( 'host' => '127.0.0.1', 'port' => '5672', 'login' => ...

  7. Django安装配置

    django2.0基础 一.安装与项目的创建 1.安装 pip install django 2.查看版本 python -m django --version 3.创建项目 django-admin ...

  8. apropos找命令助手

    apropos (意即"关于")能够搜索 Linux 帮助文档来帮你找到你想要的命令.比如说,你不记得你用的发行版用的什么防火墙工具了.你可以输入 apropos "fi ...

  9. jquery-easyui:如何设置组件属性

    在这里以面板为例: $().ready(function() { $('#menu').tree({ url : '/menu', onClick : function(node) { $('#cen ...

  10. 解决Spring配置文件不显示design和source, namespace 问题

    之前撸代码一直没太关注这个问题,后来发现对于不太熟悉配置文件内容的小伙伴们来说是比较痛苦的,因为每个配置项都需要你记住或者拷贝别人现成配置 那么问题来了,今天在写发现我的Spring配置文件不显示de ...