浅谈Java简单实现的生产者与消费者问题
一、面对生产者和消费者的问题,首先我们得明白几点:
生产者:生产数据;
消费者:消费数据。
消费者在没有数据可供消费的情况下,不能消费;
生产者在原数据没有被消费掉的情况下,不能生产新数据。
假设,数据空间只有一个。
实际上,如果实现了正确的生产和消费,则,两个线程应该是严格的交替执行。
synchronized关键字若用在代码中,形成一个同步块,且,必须要执行锁:
synchronized (锁对象) {
同步块
}
同步块使得锁对象称为thread monitor
二、代码实现:
1.首先我们建立一个生产者和消费者共同拥有的锁的类:
package com.mec.about_procuder_customer.core;
public class ProcuderCustomer {
//初始状态的数据为0个
protected static volatile int count = 0;
//执行锁
protected final static Object lock = new Object();
}
上述代码有一个关键字volatile,它是保证线程之间有序的一种方式,最重要也是最直接的是禁止寄存器优化。就是如果线程run方法中只是一个循环,并没有执行语句,那么,这个线程将不会执行。
2.我们再来建立一个生产者的类:
package com.mec.about_procuder_customer.core; //生产者
public class Procuder extends ProcuderCustomer implements Runnable { //存放数据的空间
private int[] dataSpace; public Procuder(int[] dataSpace, String threadName) {
this.dataSpace = dataSpace;
//启动线程
new Thread(this, threadName).start();
} @Override
public void run() {
int i = 0; while (true) {
synchronized (lock) {
//判断是否空间已满
if (count < dataSpace.length) {
//产生者放数据
dataSpace[count] = i++;
System.out.println("[" + Thread.currentThread().getName()
+ "]线程生产了一个数:" + dataSpace[count++]
+ " " + count);
try {
//只是为了看的清楚,沉睡2秒
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//唤醒消费者
lock.notify();
} else {
try {
//使自己处于阻塞状态
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
3.建立消费者的类:
package com.mec.about_procuder_customer.core; //消费者
public class Customer extends ProcuderCustomer implements Runnable {
//存放数据的空间
private int[] dataSpace; public Customer(int[] dataSpace, String threadName) {
this.dataSpace = dataSpace;
//启动线程
new Thread(this, threadName).start();
} @Override
public void run() {
while (true) {
//加锁
synchronized (lock) {
//判断是否有数据
if (count > 0) {
System.out.println("[" + Thread.currentThread().getName()
+ "]线程消费了一个数:" + dataSpace[--count]);
//唤醒生产者
lock.notifyAll();
} else {
try {
//使自己处于阻塞状态
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
} }
4.测试类:
package com.mec.about_procuder_customer.test; import com.mec.about_procuder_customer.core.Customer;
import com.mec.about_procuder_customer.core.Procuder; public class Test { public static void main(String[] args) {
int[] data = new int[10];
new Procuder(data, "生产者1");
new Procuder(data, "生产者2");
new Customer(data, "消费者");
} }
运行结果:

浅谈Java简单实现的生产者与消费者问题的更多相关文章
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈Java中的equals和==(转)
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: 1 String str1 = new String("hello"); 2 String str ...
- 浅谈Java中的equals和==
浅谈Java中的equals和== 在初学Java时,可能会经常碰到下面的代码: String str1 = new String("hello"); String str2 = ...
- 浅谈java性能分析
浅谈java性能分析,效能分析 在老师强烈的要求下做了效能分析,对上次写过的词频统计的程序进行分析以及改进. 对于效能分析:我个人很浅显的认为就是程序的运行效率,代码的执行效率等等. java做性能测 ...
- 浅谈Java中的深拷贝和浅拷贝(转载)
浅谈Java中的深拷贝和浅拷贝(转载) 原文链接: http://blog.csdn.net/tounaobun/article/details/8491392 假如说你想复制一个简单变量.很简单: ...
- !! 浅谈Java学习方法和后期面试技巧
浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...
- 浅谈Java中的深拷贝和浅拷贝
转载: 浅谈Java中的深拷贝和浅拷贝 假如说你想复制一个简单变量.很简单: int apples = 5; int pears = apples; 不仅仅是int类型,其它七种原始数据类型(bool ...
- 【转】浅谈Java中的hashcode方法(这个demo可以多看看)
浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...
- 浅谈java类集框架和数据结构(2)
继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...
随机推荐
- php 把秒数转换为时长(h:i:s格式)
/** * 把秒数转换为时分秒的格式 * @param Int $times 时间,单位 秒 * @return String */ function secToTime($times){ $resu ...
- PyCharm 安装及破解方法
PyCharm 安装及破解方法 一.安装 首先要下载Pycharm这个软件,可以在官网下载进行下载. 下载完软件之后,双击安装文件即可进行安装,双击后出现下图所示的提示,点击Next即可. 然后会出现 ...
- oracle 11g SKIP_UNUSABLE_INDEXES参数
SKIP_UNUSABLE_INDEXES的作用是在DML期间跳过对索引的维护,这样可以提交DML的效率,可以事后一次性重建,但是SKIP_UNUSABLE_INDEXES=y对unique inde ...
- GitHub客户端使用
GitHub客户端使用 我们今天先讲解一下Github for windows(客户端)的使用方法,之后我们会以一个实例一步一步的来讲解Github. Github for windows(客户端)是 ...
- 使用liner、feather、multiband对已经拼接的数据进行融合(下)
理解mulitband.所谓的mulitband,其实就是一种多尺度的样条融合,其实现的主要方法就是laplace金字塔. 高斯金字塔是向下采样,而laplace金字塔式向上采样(也就是恢复),采用的 ...
- 用C++调用tensorflow在python下训练好的模型(centos7)
本文主要参考博客https://blog.csdn.net/luoyexuge/article/details/80399265 [1] bazel安装参考:https://blog.csdn.net ...
- USB通信基础知识
1 USB系统组成 主机:提供USB接口和接口管理功能的硬件.软件.固件的复合体.PC机或OTG设备,一个USB系统只能有一个主机 设备:1.集线器HUB:扩展主机接口,设备可以通过其接入主机 2. ...
- Eclipse自动生成方法注释 快捷键
自动生成方法的注释格式,例如 /*** @param str* @return* @throws ParseException*/ 快捷键是 ALT + SHIFT + J,将光标放在方法名上,按快捷 ...
- 16 级高代 II 思考题十的多种证明
16 级高代 II 思考题十 设 $V$ 是数域 $\mathbb{K}$ 上的 $n$ 维线性空间, $\varphi$ 是 $V$ 上的线性变换, 证明: $\varphi$ 的极小多项式 $m ...
- java中读取配置文件的方法
转自:http://blog.csdn.net/stypace/article/details/38414871 一.使用org.apache.commons.configuration 需要使用的是 ...