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 ...
随机推荐
- ios TextField限制输入两位小数
只需要实现textField的这个代理方法就可以实现 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange: ...
- NOIP2016-D2-T2 蚯蚓(单调队列)
构建三个单调队列(用STL),分别储存未切的蚯蚓,切后的第一段,切后的第二段,即可简单证明其单调性. 证明:设$q$为单调队列$\because a_1 \geqslant a_2 \geqslant ...
- Js表单验证控件
演示地址:http://weishakeji.net/Utility/Verify/Index.htm 开源地址:https://github.com/weishakeji/Verify_Js ...
- 设置linux的console为串口【转】
转自:http://blog.chinaunix.net/uid-27717694-id-4074219.html 以Grub2为例:1. 修改文件/etc/default/grub #显示启动菜 ...
- Gitlab & Github
windwos上Git的使用 软件下载地址:https://github.com/git-for-windows/git/releases/download/v2.15.1.windows.2/Git ...
- c++中的类(class)
c++的class(类)使用方法 这几天一直在调splay之类的东西,突然想转指针...qwq 于是,我就在沙华大佬的帮助下,学了下一顿乱指( $ -> $ ),也就是class(类) 首先:c ...
- Java Map 接口
Map接口中键和值一一映射. 可以通过键来获取值. 给定一个键和一个值,你可以将该值存储在一个Map对象. 之后,你可以通过键来访问对应的值. 当访问的值不存在的时候,方法就会抛出一个NoSuchEl ...
- Bootstrap fileinput.js,最好用的文件上传组件
本篇介绍如何使用bootstrap fileinput.js(最好用的文件上传组件)来进行图片的展示,上传,包括springMVC后端文件保存. 一.demo 二.插件引入 <link ty ...
- SpringMVC高级参数绑定(数组和List)
本节内容: 参数绑定之数组 将表单的数据绑定到List 复制下上篇博客中的工程,作为今天开发的工程. 一.参数绑定之数组 1. 需求 在商品列表页面选中多个商品,然后删除. 2. 需求分析 功能要求商 ...
- Action的模型绑定
- 你真的会用Action的模型绑定吗? 在QQ群或者一些程序的交流平台,经常会有人问:我怎么传一个数组在Action中接收.我传的数组为什么Action的model中接收不到.或者我在ajax的 ...