java 实现生产者-消费者模式
生产和消费者模式有很多种,现在介绍几种常见的方式
- 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 实现生产者-消费者模式的更多相关文章
- Java设计模式—生产者消费者模式(阻塞队列实现)
生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...
- java多线程 生产者消费者模式
package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...
- 关于java中生产者消费者模式的理解
在说生产者消费者模式之前,我觉得有必要理解一下 Obj.wait(),与Obj.notify()方法.wait()方法是指在持有对象锁的线程调用此方法时,会释放对象锁,同时休眠本线程.notify() ...
- java实现生产者消费者模式
生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将 ...
- java——利用生产者消费者模式思想实现简易版handler机制
参考教程:http://www.sohu.com/a/237792762_659256 首先说一下这里面涉及到的线程: 1.mainLooper: 这个线程可以理解为消费者线程,里面运行了一个死循环, ...
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
- Java 生产者消费者模式详细分析
*/ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...
- java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比
package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...
- Java 学习笔记 使用并发包ReentrantLock简化生产者消费者模式代码
说明 ReentrantLock是java官方的一个线程锁类,ReentarntLock实现了Lock的接口 我们只需要使用这个,就可以不用使用synchronized同步关键字以及对应的notify ...
随机推荐
- 蓝桥杯 大臣的旅费_树的最长度_两次DFS
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> ...
- go语言学习之路(一)Hello World
为什么要使用 Go 语言?Go 语言的优势在哪里? 1.部署简单. 2.并发性好. 3.良好的语言设计. 4.执行性能好. Go环境搭建 Golang下载 国外镜像 https://www.gola ...
- [转载]AngularJS 指令 用法
http://book.2cto.com/201312/37782.html http://www.itnose.net/detail/6144038.html http://www.cnblogs. ...
- 利用fiddler来模拟低速环境
为了让我们的站点拥有更好的用户体验,更短的加载时间,我们会“按需加载”页面的资源. 在调试程序的时候,我们希望能有一个低速率的网络环境来模拟真实线上的环境,这个时候fiddler(下载fiddler请 ...
- xmlhttprequest upload
html5 带进度上传 function fileSelected() { var file = document.getElementById('fileToUpload').files[0]; i ...
- RabbitMq简单应用
服务端: <?php //配置信息 $conn_args = array( 'host' => '127.0.0.1', 'port' => '5672', 'login' => ...
- Django安装配置
django2.0基础 一.安装与项目的创建 1.安装 pip install django 2.查看版本 python -m django --version 3.创建项目 django-admin ...
- apropos找命令助手
apropos (意即"关于")能够搜索 Linux 帮助文档来帮你找到你想要的命令.比如说,你不记得你用的发行版用的什么防火墙工具了.你可以输入 apropos "fi ...
- jquery-easyui:如何设置组件属性
在这里以面板为例: $().ready(function() { $('#menu').tree({ url : '/menu', onClick : function(node) { $('#cen ...
- 解决Spring配置文件不显示design和source, namespace 问题
之前撸代码一直没太关注这个问题,后来发现对于不太熟悉配置文件内容的小伙伴们来说是比较痛苦的,因为每个配置项都需要你记住或者拷贝别人现成配置 那么问题来了,今天在写发现我的Spring配置文件不显示de ...