生产者消费者问题

问题描述

有两个进程:一组生产者进程和一组消费者进程共享一个初始为空、固定大小为n的缓存(缓冲区)。生产者的工作是制造一段数据,只有缓冲区没满时,生产者才能把消息放入到缓冲区,否则必须等待,如此反复; 同时,只有缓冲区不空时,消费者才能从中取出消息,一次消费一段数据(即将其从缓存中移出),否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或者一个消费者从中取出消息。

代码实现

public class ProducerConsumer {

	public static void main(String[] args) {
Basket basket = new Basket();
Producer producer = new Producer(basket);
Consumer consumer = new Consumer(basket);
new Thread(producer).start();
new Thread(consumer).start();
}
} class Basket { //存放产品
int index = 0;
static final int MAX_CAPICITY = 10;
static final int MIN_CAPICITY = 0;
Product[] arrproduct = new Product[MAX_CAPICITY]; public synchronized void push(Product product) { //生产指令
while (index == MAX_CAPICITY) { //当产量等于最大容量是进入等待状态
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} this.notify(); //告知消费者进行消费
arrproduct[index] = product;
index++;
} public synchronized Product pop() { //消费指令
while (index == MIN_CAPICITY) { //当消费量等于最小容量时进入等待状态
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} this.notify(); //告知生产者进行生产
index--;
return arrproduct[index];
}
} class Product {
int id; Product(int id) {
this.id = id;
} @Override
public String toString() {
return "product id--" + id;
}
} class Producer implements Runnable {
Basket basket = null;
Producer(Basket basket) {
this.basket = basket;
} public void run() {
for (int i = 0; i < 20; i++) {
Product product = new Product(i);
basket.push(product);
System.out.println("生产了:" + product);
try {
Thread.sleep((int)(Math.random()*200));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
} class Consumer implements Runnable {
Basket basket = null;
Consumer(Basket basket) {
this.basket = basket;
} public void run() {
for (int i = 0; i < 20; i++) {
Product product = basket.pop();
System.out.println("消费了:" + product);
try {
Thread.sleep((int)(Math.random()*1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

样例输出

消费了:product id--0
生产了:product id--0
生产了:product id--1
生产了:product id--2
生产了:product id--3
消费了:product id--3
消费了:product id--2
生产了:product id--4
生产了:product id--5
生产了:product id--6
生产了:product id--7
生产了:product id--8
生产了:product id--9
消费了:product id--9
生产了:product id--10
生产了:product id--11
生产了:product id--12
生产了:product id--13
消费了:product id--13
消费了:product id--12
生产了:product id--14
生产了:product id--15
消费了:product id--15
生产了:product id--16
消费了:product id--16
生产了:product id--17
消费了:product id--17
生产了:product id--18
消费了:product id--18
生产了:product id--19
消费了:product id--19
消费了:product id--14
消费了:product id--11
消费了:product id--10
消费了:product id--8
消费了:product id--7
消费了:product id--6
消费了:product id--5
消费了:product id--4
消费了:product id--1

JavaDay10(下)的更多相关文章

  1. C++程序结构---1

    C++ 基础教程Beta 版 原作:Juan Soulié 翻译:Jing Xu (aqua) 英文原版 本教程根据Juan Soulie的英文版C++教程翻译并改编. 本版为最新校对版,尚未定稿.如 ...

  2. Android SwipeRefreshLayout 下拉刷新——Hi_博客 Android App 开发笔记

    以前写下拉刷新 感觉好费劲,要判断ListView是否滚到顶部,还要加载头布局,还要控制 头布局的状态,等等一大堆.感觉麻烦死了.今天学习了SwipeRefreshLayout 的用法,来分享一下,有 ...

  3. IE6、7下html标签间存在空白符,导致渲染后占用多余空白位置的原因及解决方法

    直接上图:原因:该div包含的内容是靠后台进行print操作,输出的.如果没有输出任何内容,浏览器会默认给该空白区域添加空白符.在IE6.7下,浏览器解析渲染时,会认为空白符也是占位置的,默认其具有字 ...

  4. Ubuntu下使用nvm

    写在前面:刚写着写着博客就跨年了,希望新的一年大家万事如意,一切向"前"看! 安装 wget -qO- https://raw.githubusercontent.com/crea ...

  5. Cmder--Windows下命令行利器

    cmder cmder是一个增强型命令行工具,不仅可以使用windows下的所有命令,更爽的是可以使用linux的命令,shell命令. 安装包 安装包链接 下载后,直接解压即用. 修改命令提示符λ为 ...

  6. NodeJs在Linux下使用的各种问题

    环境:ubuntu16.04 ubuntu中安装NodeJs 通过apt-get命令安装后发现只能使用nodejs,而没有node命令 如果想避免这种情况请看下面连接的这种安装方式: 拓展见:Linu ...

  7. GreenDao 数据库:使用Raw文件夹下的数据库文件以及数据库升级

    一.使用Raw文件夹下的数据库文件 在使用GreenDao框架时,数据库和数据表都是根据生成的框架代码来自动创建的,从生成的DaoMaster中的OpenHelper类可以看出: public sta ...

  8. [APUE]UNIX进程的环境(下)

    一.共享库 共享库使得可执行文件中不再需要包含常用的库函数,而只需在所有进程都可存取的存储区中保存这种库例程的一个副本.程序第一次执行的时候或第一次调用某个库函数的时候,用动态链接方法将程序与共享库函 ...

  9. ASP.NET Aries 入门开发教程4:查询区的下拉配置

    背景: 今天去深圳溜达了一天,刚回来,看到首页都是微软大法好,看来离.NET的春天就差3个月了~~ 回到正题,这篇的教程讲解下拉配置. 查询区的下拉配置: 1:查询框怎么配置成下拉? 在配置表头:格式 ...

随机推荐

  1. 微信小程序面试题总结

    A类问题 1 请谈谈微信小程序主要目录和文件的作用? project.config.json 项目配置文件,用得最多的就是配置是否开启https校验: App.js 设置一些全局的基础数据等: App ...

  2. 《C# GDI+ 破境之道》:第一境 GDI+基础 —— 第三节:画圆形

    有了上一节画矩形的基础,画圆形就不要太轻松+EZ:)所以,本节在画边线及填充上,就不做过多的讲解了,关注一下画“随机椭圆”.“正圆”.“路径填充”的具体实现就好.与画矩形相比较,画椭圆与之完全一致,没 ...

  3. 一. 数据分片和路由 <<大数据日知录>> 读书笔记

    本章主要讲解大数据下如何做数据分片,所谓分片,即将大量数据分散在不同的节点,同时每个存储节点还要做副本备份. 而一般的抽象分片方法是, 先将数据映射到一个分片空间,这是多对一的关系,即一个数据分片区间 ...

  4. 数据算法 --hadoop/spark数据处理技巧 --(5.移动平均 6. 数据挖掘之购物篮分析MBA)

    五.移动平均 多个连续周期的时间序列数据平均值(按相同时间间隔得到的观察值,如每小时一次或每天一次)称为移动平均.之所以称之为移动,是因为随着新的时间序列数据的到来,要不断重新计算这个平均值,由于会删 ...

  5. 第二篇 Springboot mybatis generate根据数据库表自动生成实体类、Mapper和Mapper.xml

    源码链接:https://pan.baidu.com/s/1iP4UguBufHbcIEv4Ux4wDw 提取码:j6z9 目录结构如下:只需增加一个generatorConfig.xml文件和在po ...

  6. C语言基础五 数组

    数组跟变量的区别? 数组是可以在内存中连续存储多个元素的结构,所有元素必须属于相同类型. 格式:元素类型 数组名[元素个数]: 数组的特点: 只能存放单一元素的数据,里面存放的数据成为元素. 数组的声 ...

  7. JMeter-命令行模式压测

    前言 使用非GUI模式,即命令行模式运行jmeter测试脚本能够大大缩减系统资源,今天跟小伙伴们讲一下JMeter如何在命令行模式进行压测吧! 一:配置好JDK和JMeter的环境变量(过程略) 二: ...

  8. ubuntu18.04管理redis

    ubuntu下 redis的安装使用 安装 1. 进入redis安装路径 cd ~/installed/redis-5.0.7 2. 启动redis 启动服务端redis-server 启动客户端(必 ...

  9. linux 基础入门(8) 软件安装 rpm、yum与源码安装详解

    8.软件 RPM包安装 8.1rpm安装 rpm[选项]软件包名称 主选项 -i 安装 -e卸载 -U升级 -q查找 辅助选项 -ⅴ显示过程 -h --hash 查询 -a-all查询所有安装的包 - ...

  10. 机器学习算法——kNN

    顶级数据挖掘会议ICDM于2006年12月评选出了数据挖掘领域的十大经典算法,kNN便是其中一个. kNN算法的思想是:在训练集中选取与输入数据最近的k个邻居,统计k个邻居中出现次数最多的类别,以此作 ...