java实现生产者消费者模式
生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经放入产品的缓冲区中再次投放产品。
使用synchronized关键字实现线程同步
在使用wait()和notifyAll()方法时,应注意将wait()方法放入循环中,否则会产生虚假唤醒问题。
/**
* Created by 吴海飞 on 2017-1-23.
*/
public class TestProductAndConsumer {
public static void main(String[] args){
Clerk clerk = new Clerk();
Productor pro = new Productor(clerk);
Consumer consumer = new Consumer(clerk);
new Thread(pro,"生产者A").start();
new Thread(consumer,"消费者B").start();
}
}
/**
* 店员,可以进货与销售货物
*/
class Clerk{
private int product = 0;
/**
* 进货的方法
*/
public synchronized void get(){
while (product>=1){//为了避免虚假唤醒问题,应该总是使用在循环中
System.out.println("产品已满!");
try {
this.wait();//等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ":" + ++product);
this.notifyAll();//唤醒线程
}
/**
* 销售的方法
*/
public synchronized void sale(){
while (product<=0){//为避免虚假唤醒,应该总是始终使用在循环中
System.out.println("缺货……");
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ":"+ --product);
this.notifyAll();
}
}
/**
* 生产者
*/
class Productor implements Runnable{
private Clerk clerk;
public Productor(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.get();
}
}
}
/**
* 消费者
*/
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i < 10; i++){
clerk.sale();
}
}
}
使用同步锁实现线程同步问题
使用同步锁时应注意lock()与unlock()方法的同步使用。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 使用ReentrantLock实现生产者消费者问题
* Created by 吴海飞 on 2017-1-23.
*/
public class TestReentrantLock {
public static void main(String[] args){
Clerk clerk = new Clerk();
Productor pro = new Productor(clerk);
Consumer consumer = new Consumer(clerk);
new Thread(pro,"生产者A").start();
new Thread(consumer,"消费者B").start();
new Thread(pro,"生产者C").start();
new Thread(consumer,"消费者D").start();
}
}
class Clerk{
private Lock lock = new ReentrantLock();//获取同步锁
private Condition condition = lock.newCondition();
private int product = 0;
/**
* 进货的方法
*/
public void get(){
lock.lock();//打开锁
try{
while (product>=1){//为了避免虚假唤醒问题,应该总是使用在循环中
System.out.println("产品已满!");
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ":" + ++product);
condition.signalAll();
}finally {
lock.unlock();//关闭锁
}
}
/**
* 销售的方法
*/
public void sale(){
lock.lock();//加锁
try {
while (product<=0){//为避免虚假唤醒,应该总是始终使用在循环中
System.out.println("缺货……");
try {
condition.await();//等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ":"+ --product);
condition.signalAll();//唤醒等待
}finally {
lock.unlock();//释放锁
}
}
}
/**
* 生产者
*/
class Productor implements Runnable{
private Clerk clerk;
public Productor(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i < 10; i++){
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
clerk.get();
}
}
}
/**
* 消费者
*/
class Consumer implements Runnable{
private Clerk clerk;
public Consumer(Clerk clerk){
this.clerk = clerk;
}
@Override
public void run() {
for (int i = 0; i < 10; i++){
clerk.sale();
}
}
}
java实现生产者消费者模式的更多相关文章
- Java设计模式—生产者消费者模式(阻塞队列实现)
生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...
- java多线程 生产者消费者模式
package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...
- 关于java中生产者消费者模式的理解
在说生产者消费者模式之前,我觉得有必要理解一下 Obj.wait(),与Obj.notify()方法.wait()方法是指在持有对象锁的线程调用此方法时,会释放对象锁,同时休眠本线程.notify() ...
- java 实现生产者-消费者模式
生产和消费者模式有很多种,现在介绍几种常见的方式 wait/notify实现生产和消费者模式 1.使用wait/notify实现生产和消费者模式: public class Depot { // 实际 ...
- 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 ...
随机推荐
- [调试日志]用php函数var_export把多维数组file_put_contents写入并打印到日志,以方便调试之多维数组,用php5中的var_export函数示例,顺带介绍http_build_query(转)
一行解决写入日志: file_put_contents("/tmp/jack.txt", var_export($layReturnArr,TRUE),FILE_APPEND); ...
- inotify 同步脚本
#!/bin/bash path1=/home/htoa/tomcat/webapps/ROOT/htoa/ ip=192.168.30.13 /usr/bin/inotifywait -mrq -- ...
- MySQL 更新失效
create table t(id int not null PRIMARY key,c int default null) engine=innodb;insert into t(id,c)valu ...
- python-xlrd api
1.导入模块 import xlrd from xlrd import open_workbook 2.打开Excel文件读取数据 data = xlrd.open_workbook('excelFi ...
- 反向索引(Inverted Index)
转自:http://zhangyu8374.iteye.com/blog/86307 反向索引是一种索引结构,它存储了单词与单词自身在一个或多个文档中所在位置之间的映射.反向索引通常利用关联数组实现. ...
- DAY9-python并发之多进程
一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.P ...
- DAY5-常用模块
一 time与datetime模块 二.random模块 三.os模块 四.sys模块 五 shutil模块 六 json&pickle模块 七 shelve模块 八 xml模块 九 conf ...
- vmstat详细说明
下面是关于Unix下vmstat命令的详细介绍,收录在这里,以备日后参考 vmstat是用来实时查看内存使用情况,反映的情况比用top直观一些.作为一个CPU监视器,vmstat命令比iostat命令 ...
- Ajax笔记(二)
JSON基本概念: JSON:javaScript对象表示法(JavaScript Object Notation) JSON是存储和交换文本信息的语法,类似XML.它采用键值对的方式来组织,易于人们 ...
- java中的面向对象的三大基本特征
转载,原文来自http://blog.sina.com.cn/s/blog_5f79a56a0100c6ig.html 众所周知,java中的面向对象的三大基本特征是:[封装].[继承].[多态] 一 ...