生产者消费者问题是一个著名的线程同步问题,该问题描述如下:有一个生产者在生产产品,这些产品将提供给若干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个具有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲区中取走产品进行消费,显然生产者和消费者之间必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经放入产品的缓冲区中再次投放产品。

使用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实现生产者消费者模式的更多相关文章

  1. Java设计模式—生产者消费者模式(阻塞队列实现)

    生产者消费者模式是并发.多线程编程中经典的设计模式,生产者和消费者通过分离的执行工作解耦,简化了开发模式,生产者和消费者可以以不同的速度生产和消费数据.这篇文章我们来看看什么是生产者消费者模式,这个问 ...

  2. java多线程 生产者消费者模式

    package de.bvb; /** * 生产者消费者模式 * 通过 wait() 和 notify() 通信方法实现 * */ public class Test1 { public static ...

  3. 关于java中生产者消费者模式的理解

    在说生产者消费者模式之前,我觉得有必要理解一下 Obj.wait(),与Obj.notify()方法.wait()方法是指在持有对象锁的线程调用此方法时,会释放对象锁,同时休眠本线程.notify() ...

  4. java 实现生产者-消费者模式

    生产和消费者模式有很多种,现在介绍几种常见的方式 wait/notify实现生产和消费者模式 1.使用wait/notify实现生产和消费者模式: public class Depot { // 实际 ...

  5. java——利用生产者消费者模式思想实现简易版handler机制

    参考教程:http://www.sohu.com/a/237792762_659256 首先说一下这里面涉及到的线程: 1.mainLooper: 这个线程可以理解为消费者线程,里面运行了一个死循环, ...

  6. java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-【费元星Q9715234】

    java+反射+多线程+生产者消费者模式+读取xml(SAX)入数据库mysql-[费元星Q9715234] 说明如下,不懂的问题直接我[费元星Q9715234] 1.反射的意义在于不将xml tag ...

  7. Java 生产者消费者模式详细分析

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  8. java ReentrantLock结合条件队列 实现生产者-消费者模式 以及ReentratLock和Synchronized对比

    package reentrantlock; import java.util.ArrayList; public class ProviderAndConsumerTest { static Pro ...

  9. Java 学习笔记 使用并发包ReentrantLock简化生产者消费者模式代码

    说明 ReentrantLock是java官方的一个线程锁类,ReentarntLock实现了Lock的接口 我们只需要使用这个,就可以不用使用synchronized同步关键字以及对应的notify ...

随机推荐

  1. 一般处理程序+html 的CRUD

    using Console_Core.BLL; using Console_Core.Common; using Console_Core.Model; using System; using Sys ...

  2. 蓝桥杯 历届试题 PREV-32 分糖果

    历届试题 分糖果   时间限制:1.0s   内存限制:256.0MB 问题描述 有n个小朋友围坐成一圈.老师给每个小朋友随机发偶数个糖果,然后进行下面的游戏: 每个小朋友都把自己的糖果分一半给左手边 ...

  3. 转载:MongoDB 在 58 同城百亿量级数据下的应用实践

    为什么要使用 MongoDB? MongoDB 这个来源英文单词“humongous”,homongous 这个单词的意思是“巨大的”.“奇大无比的”,从 MongoDB 单词本身可以看出它的目标是提 ...

  4. $route路由

    <!DOCTYPE html><html ng-app="AngularApp"> <head> <meta charset=" ...

  5. mjpg-streamer在Ubuntu下编译,运行

    1.将USB摄像头插上,查看是否找到设备,输入: wp@ubuntu:/home/$    ls   /dev/video* /dev/video0 2.安装必要的软件集: sudo apt-get ...

  6. PHP类(一)-类的实例化

    类的实例化就是对象.一个类可以分成两个部分,一个是静态描述,就是类里的成员属性.第二个是动态描述,就是类里的成员方法,也就是对象的功能. 声明一个类,可以在class前加一些关键字,如abstract ...

  7. PDM后续处理-驼峰规则、清除约束、外键改名

    Option   Explicit ValidationMode   =   True InteractiveMode =   im_Batch Dim   mdl   '当前model '获取当前活 ...

  8. 带坑的几道PHP面试题

    第二题 代码如下: $i='11'; printf("%d\n",printf("%d",printf("%d",$i))); 输出结果是多 ...

  9. enable or disable Oracle block change tracking

    Oracle的block change tracking用于记录上次备份以来改变过的block信息,因此打开block change tracking可以大大加快增量备份的速度. 1. Enable ...

  10. Datapump tips

    同时导出多个schema下的表 $ expdp system/manager dumpfile=test.dmp logfile=test.log directory=TESTDIR schemas= ...