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 ...
随机推荐
- bzoj 3160 万径人踪灭——FFT
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3160 似乎理解加深了. 用卷积算相同的位置:先把 a 赋成1. b 赋成0,卷积一遍:再把 ...
- laravel 判断上传文件的类型和后缀
学习源头: https://blog.csdn.net/ddjjll8877/article/details/52249965 class FileUpdateController extends B ...
- java代码----方法类练习中~~~未领会
总结:今天我很失败,问了老师继承的问题还是没弄懂.因为,技术宅的能力,我好怕啊.太强了. package com.da.ima2; public class yut {// 使用substring方法 ...
- 使用Spring AMQP开发消费者应用
前一篇中我们介绍了使用RabbitMQ Java Client访问RabbitMQ的方法.但是使用这种方式访问RabbitMQ,开发者在程序中需要自己管理Connection,Channel对象,Co ...
- git教程(远程仓库和管理分支)
在github上新建了一个仓库,然后相与本地的仓库联系起来 $ Git remote add origin https://github.com/liona329/learngit.git fatal ...
- 深入VR之前 你应该知道VR头显透镜原理
转自:http://www.gamelook.com.cn/2016/03/246817 要理解虚拟现实头显透镜的工作原理,首先要搞懂眼睛是如何看到事物的. 眼睛瞳孔后有晶状体,也就是眼珠子.眼睛的背 ...
- Celery-4.1 用户指南: Configuration and defaults (配置和默认值)
这篇文档描述了可用的配置选项. 如果你使用默认的加载器,你必须创建 celeryconfig.py 模块并且保证它在python路径中. 配置文件示例 以下是配置示例,你可以从这个开始.它包括运行一个 ...
- [Python Study Notes]物体运动检测
基于opencv的cv2模块实现 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' ...
- B和strong以及i和em的区别(转)
B和strong以及i和em的区别 (2013-12-31 13:58:35) 标签: b strong i em 搜索引擎 分类: 网页制作 一直以来都以为B和strong以及i和em是相同的效果, ...
- c++ public protected private 继承
1:访问控制 1.1 public 这类型成员可以被类本身函数访问,也可以被外部创建的类对象调用.子类对象与子类内部可以访问 1.2 protected类型成员,只能被类本身函数访问.外部创建的类对象 ...