Java——Java实现生产者消费者
1、生产/消费者模型
生产/消费者问题是个非常典型的多线程问题,涉及到的对象包括“生产者”、“消费者”、“仓库”和“产品”。他们之间的关系如下:
(01) 生产者仅仅在仓储未满时候生产,仓满则停止生产。
(02) 消费者仅仅在仓储有产品时候才能消费,仓空则等待。
(03) 当消费者发现仓储没产品可消费时候会通知生产者生产。
(04) 生产者在生产出可消费产品时候,应该通知等待的消费者去消费。
2、生产者消费者实现(synchronized )
// Demo1.java
// 仓库
class Depot {
private int capacity; // 仓库的容量
private int size; // 仓库的实际数量
public Depot(int capacity) {
this.capacity = capacity;
this.size = 0;
}
public synchronized void produce(int val) {
try {
// left 表示“想要生产的数量”(有可能生产量太多,需多此生产)
int left = val;
while (left > 0) {
// 库存已满时,等待“消费者”消费产品。
while (size >= capacity)
wait();
// 获取“实际生产的数量”(即库存中新增的数量)
// 如果“库存”+“想要生产的数量”>“总的容量”,则“实际增量”=“总的容量”-“当前容量”。(此时填满仓库)
// 否则“实际增量”=“想要生产的数量”
int inc = (size+left)>capacity ? (capacity-size) : left;
size += inc;
left -= inc;
System.out.printf("%s produce(%3d) --> left=%3d, inc=%3d, size=%3d\n",
Thread.currentThread().getName(), val, left, inc, size);
// 通知“消费者”可以消费了。
notifyAll();
}
} catch (InterruptedException e) {
}
}
public synchronized void consume(int val) {
try {
// left 表示“客户要消费数量”(有可能消费量太大,库存不够,需多此消费)
int left = val;
while (left > 0) {
// 库存为0时,等待“生产者”生产产品。
while (size <= 0)
wait();
// 获取“实际消费的数量”(即库存中实际减少的数量)
// 如果“库存”<“客户要消费的数量”,则“实际消费量”=“库存”;
// 否则,“实际消费量”=“客户要消费的数量”。
int dec = (size<left) ? size : left;
size -= dec;
left -= dec;
System.out.printf("%s consume(%3d) <-- left=%3d, dec=%3d, size=%3d\n",
Thread.currentThread().getName(), val, left, dec, size);
notifyAll();
}
} catch (InterruptedException e) {
}
}
public String toString() {
return "capacity:"+capacity+", actual size:"+size;
}
}
// 生产者
class Producer {
private Depot depot;
public Producer(Depot depot) {
this.depot = depot;
}
// 消费产品:新建一个线程向仓库中生产产品。
public void produce(final int val) {
new Thread() {
public void run() {
depot.produce(val);
}
}.start();
}
}
// 消费者
class Customer {
private Depot depot;
public Customer(Depot depot) {
this.depot = depot;
}
// 消费产品:新建一个线程从仓库中消费产品。
public void consume(final int val) {
new Thread() {
public void run() {
depot.consume(val);
}
}.start();
}
}
public class Demo1 {
public static void main(String[] args) {
Depot mDepot = new Depot(100);
Producer mPro = new Producer(mDepot);
Customer mCus = new Customer(mDepot);
mPro.produce(60);
mPro.produce(120);
mCus.consume(90);
mCus.consume(150);
mPro.produce(110);
}
}
运行结果
Thread-0 produce( 60) --> left= 0, inc= 60, size= 60
Thread-4 produce(110) --> left= 70, inc= 40, size=100
Thread-2 consume( 90) <-- left= 0, dec= 90, size= 10
Thread-3 consume(150) <-- left=140, dec= 10, size= 0
Thread-1 produce(120) --> left= 20, inc=100, size=100
Thread-3 consume(150) <-- left= 40, dec=100, size= 0
Thread-4 produce(110) --> left= 0, inc= 70, size= 70
Thread-3 consume(150) <-- left= 0, dec= 40, size= 30
Thread-1 produce(120) --> left= 0, inc= 20, size= 50
3、生产者消费者实现(Lock锁)
package Thread;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Depot{
private int capacity; //仓库容量
private int size; //仓库当前产品数量
private Lock lock; //锁
private Condition productCondition; //生产条件
private Condition consumerCondition; //消费条件
public Depot(int capacity) {
this.capacity=capacity;
this.size=0;
this.lock = new ReentrantLock();
this.productCondition = this.lock.newCondition();
this.consumerCondition = this.lock.newCondition();
}
//生产商品
public void produce(int val) {
lock.lock();
try {
int left=val; //left表示需要生产的数量
while (left > 0) {
//当库存已满时,则生产者开始等待消费者消费
while (size == capacity) {
productCondition.await();
}
int pro= left > (capacity-size) ? (capacity-size) : left; //如果生产的数量大于仓库容量,则只生产仓库容量这么多
size += pro;
left -= pro;
System.out.printf("%s produce(%3d) --> left=%3d, inc=%3d, size=%3d\n",
Thread.currentThread().getName(), val, left, pro, size);
consumerCondition.signal(); //消费者消费时,发现当仓库产品为零时,此时消费者等待,调用生产者生产,那么生产者生产完成后则需要释放消费者
}
}catch (Exception e){
}finally {
lock.unlock();
}
}
//消费商品
public void consume(int val) {
lock.lock();
try {
int left=val; //left表示需要消费的数量
while (left > 0) {
while (size == 0) { //当前商品数量为零时,消费者需要等待
consumerCondition.await();
}
int cus=left > size? size : left;
size -= cus;
left -= cus;
System.out.printf("%s consume(%3d) <-- left=%3d, dec=%3d, size=%3d\n",
Thread.currentThread().getName(), val, left, cus, size);
productCondition.signal(); //消费者消费完成后,需要释放生产者
}
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
//生产者
class Producer{
private Depot depot;
public Producer(Depot depot) {
this.depot = depot;
}
public void produce(int val){
new Thread(){
@Override
public void run() {
depot.produce(val);
}
}.start();
}
}
//消费者
class Customer{
private Depot depot;
public Customer(Depot depot) {
this.depot = depot;
}
public void consume(int val) {
new Thread(){
@Override
public void run() {
depot.consume(val);
}
}.start();
}
}
public class LockTest {
public static void main(String[] args) {
Depot mDepot = new Depot(100);
Producer mPro = new Producer(mDepot);
Customer mCus = new Customer(mDepot);
mPro.produce(60);
mPro.produce(120);
mCus.consume(90);
mCus.consume(150);
mPro.produce(110);
}
}
运行结果
Thread-0 produce( 60) --> left= 0, inc= 60, size= 60
Thread-1 produce(120) --> left= 80, inc= 40, size=100
Thread-2 consume( 90) <-- left= 0, dec= 90, size= 10
Thread-3 consume(150) <-- left=140, dec= 10, size= 0
Thread-4 produce(110) --> left= 10, inc=100, size=100
Thread-3 consume(150) <-- left= 40, dec=100, size= 0
Thread-4 produce(110) --> left= 0, inc= 10, size= 10
Thread-3 consume(150) <-- left= 30, dec= 10, size= 0
Thread-1 produce(120) --> left= 0, inc= 80, size= 80
Thread-3 consume(150) <-- left= 0, dec= 30, size= 50
Java——Java实现生产者消费者的更多相关文章
- 第23章 java线程通信——生产者/消费者模型案例
第23章 java线程通信--生产者/消费者模型案例 1.案例: package com.rocco; /** * 生产者消费者问题,涉及到几个类 * 第一,这个问题本身就是一个类,即主类 * 第二, ...
- java多线程解决生产者消费者问题
import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class ...
- java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】
java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...
- Java设计模式之生产者消费者模式
Java设计模式之生产者消费者模式 博客分类: 设计模式 设计模式Java多线程编程thread 转载 对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一 ...
- java多线程模拟生产者消费者问题,公司面试常常问的题。。。
package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 // ...
- JAVA多线程之生产者 消费者模式 妈妈做面包案例
创建四个类 1.面包类 锅里只可以放10个面包 ---装面包的容器2.厨房 kitchen 生产面包 和消费面包 最多生产100个面包3.生产者4消费者5.测试类 多线程经典案例 import ja ...
- Java里的生产者-消费者模型(Producer and Consumer Pattern in Java)
生产者-消费者模型是多线程问题里面的经典问题,也是面试的常见问题.有如下几个常见的实现方法: 1. wait()/notify() 2. lock & condition 3. Blockin ...
- Java并发之:生产者消费者问题
生产者消费者问题是Java并发中的常见问题之一,在实现时,一般可以考虑使用juc包下的BlockingQueue接口,至于具体使用哪个类,则就需要根据具体的使用场景具体分析了.本文主要实现一个生产者消 ...
- Java多线程同步——生产者消费者问题
这是马士兵老师的Java视频教程里的一个生产者消费者问题的模型 public class ProduceConsumer{ public static void main(String[] args) ...
- java模拟实现生产者---消费者问题
本文章为小编原创,请尊重文章的原创性,转载请注意写明转载来源:http://blog.csdn.net/u012116457 已知技术參数: 生产者消费者问题,描写叙述一组生产者向一组消费者提供产品/ ...
随机推荐
- 条件变量 condition_variable wait_for
wait_for(阻塞当前线程,直到条件变量被唤醒,或到指定时限时长后) #include <iostream> #include <atomic> #include < ...
- Codeup 25593 Problem G 例题5-7 求圆周率pi的近似值
题目描述 用如下公式 4*Π = 1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + 1/13 - 1/15 - 求圆周率PI的近似值,直到发现某一项的绝对值小于10-6为止(该项不 ...
- Web 如何搭建自己的个人网站
如何搭建自己的个人技术博客网站 学习目标 1.[了解]搭建网站需要的web构件和网站运行原理 2.[掌握]如何搭建个人博客网站 学习前言 大家都是学习开发的,相信都接触过百度,新浪,淘宝,京东...等 ...
- 【乱码问题】IDEA控制台使用了GBK字符集
什么Tomcat乱码设置IDEA的初始编码,瞎搞 终于在这个帖子看到了真相 https://blog.csdn.net/weixin_42617398/article/details/81806438 ...
- animation-play-state 在 ios 中不生效的解决办法(JS篇)
我们要实现动画的播放和暂停,animation-play-state 在安卓端可以使用,但是在 ios 中不起作用,这时可以使用 js 来实现相同效果. 原理 通过 js 获取当前元素的 transf ...
- Video tagging systems based on DNNs
Need: With the ever-growth large-scale video in the mobile phone, so what will everyone get from the ...
- vue的组件通讯
Vue的组件通讯又称组件传值 一.父子组件传值: 父组件: <子组件名 :动态变量名 (随便起)='你想要传递的数据' ></子组件名> 子组件: 利用 prop去接收父组 ...
- python的历史和下载python解释器
一.python的诞生 1.Python的创始人为Guido van Rossum.1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,创造了一种C和sh ...
- MySQL学习之正则表达式篇
正则表达式(REGEXP) 1.简介 正则表达式是用来匹配列值的特殊字符集合,许多领域都有涉及, MySQL使用的正则表达式仅为其一个小小的子集. 2.基本字符匹配 2.1筛选包含特定字符串的信息 / ...
- /uesr/local/hadoop/tmp/mapred有锁
原因: /usr/local/hadoop/tmp/mapred 有锁 解决:修改改文件的权限 在终端输入: cd /usr/local/hadoop/tmp sudo chmod 777 map ...