作者要的是一个生产者生成,接着必须有一个消费者消费,那这不是需要单线程吗?或者使用1个大小的阻塞队列。所以只谈论问题本身,不谈论好不好。

具体代码:

Java代码  
  1. import java.util.concurrent.locks.Condition;
  2. import java.util.concurrent.locks.Lock;
  3. import java.util.concurrent.locks.ReentrantLock;
  4. //生产/消费者模式
  5. public class Basket {
  6. Lock lock = new ReentrantLock();
  7. // 产生Condition对象
  8. Condition produced = lock.newCondition();
  9. Condition consumed = lock.newCondition();
  10. boolean available = false;
  11. public void produce() throws InterruptedException {
  12. lock.lock();
  13. try {
  14. if (available) {
  15. produced.await(); // 放弃lock进入睡眠
  16. }
  17. System.out.println("Apple produced.");
  18. available = true;
  19. consumed.signal(); // 发信号唤醒等待这个Condition的线程
  20. } finally {
  21. lock.unlock();
  22. }
  23. }
  24. public void consume() throws InterruptedException {
  25. lock.lock();
  26. try {
  27. if (!available) {
  28. consumed.await(); // 放弃lock进入睡眠
  29. }
  30. /* 吃苹果 */
  31. System.out.println("Apple consumed.");
  32. available = false;
  33. produced.signal(); // 发信号唤醒等待这个Condition的线程
  34. } finally {
  35. lock.unlock();
  36. }
  37. }
  38. }
import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;//生产/消费者模式public class Basket {Lock lock = new ReentrantLock();// 产生Condition对象Condition produced = lock.newCondition();Condition consumed = lock.newCondition();boolean available = false;public void produce() throws InterruptedException {lock.lock();try {if (available) {produced.await(); // 放弃lock进入睡眠}System.out.println("Apple produced.");available = true;consumed.signal(); // 发信号唤醒等待这个Condition的线程} finally {lock.unlock();}}public void consume() throws InterruptedException {lock.lock();try {if (!available) {consumed.await(); // 放弃lock进入睡眠}/* 吃苹果 */System.out.println("Apple consumed.");available = false;produced.signal(); // 发信号唤醒等待这个Condition的线程} finally {lock.unlock();}}}
Java代码  
  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. //测试用类
  4. public class ConditionTester {
  5. public static void main(String[] args) throws InterruptedException {
  6. final Basket basket = new Basket();
  7. // 定义一个producer
  8. Runnable producer = new Runnable() {
  9. public void run() {
  10. try {
  11. basket.produce();
  12. } catch (InterruptedException ex) {
  13. ex.printStackTrace();
  14. }
  15. }
  16. };
  17. // 定义一个consumer
  18. Runnable consumer = new Runnable() {
  19. public void run() {
  20. try {
  21. basket.consume();
  22. } catch (InterruptedException ex) {
  23. ex.printStackTrace();
  24. }
  25. }
  26. };
  27. // 各产生10个consumer和producer
  28. ExecutorService service = Executors.newCachedThreadPool();
  29. for (int i = 0; i < 4; i++)
  30. service.submit(consumer);
  31. Thread.sleep(2000 * 2);
  32. for (int i = 0; i < 4; i++)
  33. service.submit(producer);
  34. service.shutdown();
  35. }
  36. }
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;//测试用类
public class ConditionTester {public static void main(String[] args) throws InterruptedException {final Basket basket = new Basket();// 定义一个producerRunnable producer = new Runnable() {public void run() {try {basket.produce();} catch (InterruptedException ex) {ex.printStackTrace();}}};// 定义一个consumerRunnable consumer = new Runnable() {public void run() {try {basket.consume();} catch (InterruptedException ex) {ex.printStackTrace();}}};// 各产生10个consumer和producerExecutorService service = Executors.newCachedThreadPool();for (int i = 0; i < 4; i++)service.submit(consumer);Thread.sleep(2000 * 2);for (int i = 0; i < 4; i++)service.submit(producer);service.shutdown();}
}

原因分析:

1、假设前面有2个producer(此时available=true)

1.1、一个在等待lock

1.2、一个await

2、consumer生成内容后,available=false,produced.signal(); 最后lock.unlock();

3.1、因为lock.unlock所以会触发一个lock获取到锁(虽然signal也会触发等待这个条件的其他线程,但是多线程大家都知道什么时候触发这是不确定的),如果此时正好是[1.1]那么因为available=false,执行完释放锁

3.2、produced.signal()所以会触发一个await的producer;

解决方案:

只要保证[3.1]还是需要await即可解决问题

所以加一个 AtomicInteger producedAwaitCounter = new AtomicInteger(0); 统计当前等待的生产者,如果当前available=false,但已经有生产者生成了内容,那么先等待消费者消费了再说

if (available || producedAwaitCounter.get() > 0) {

producedAwaitCounter.incrementAndGet();

produced.await(); // 放弃lock进入睡眠

producedAwaitCounter.decrementAndGet();

}

当然最简单的是使用:自旋,原理可以自己分析下:

while (available) {

produced.await(); // 放弃lock进入睡眠

}

Java代码  
  1. package com.sishuok.es.test;
  2. import java.util.concurrent.atomic.AtomicInteger;
  3. import java.util.concurrent.locks.Condition;
  4. import java.util.concurrent.locks.Lock;
  5. import java.util.concurrent.locks.ReentrantLock;
  6. //生产/消费者模式
  7. public class Basket {
  8. Lock lock = new ReentrantLock(true);
  9. // 产生Condition对象
  10. Condition produced = lock.newCondition();
  11. Condition consumed = lock.newCondition();
  12. boolean available = false;
  13. AtomicInteger producedAwaitCounter = new AtomicInteger(0);
  14. public void produce() throws InterruptedException {
  15. lock.lock();
  16. try {
  17. if (available || producedAwaitCounter.get() > 0) {
  18. producedAwaitCounter.incrementAndGet();
  19. produced.await(); // 放弃lock进入睡眠
  20. producedAwaitCounter.decrementAndGet();
  21. }
  22. System.out.println("Apple produced.");
  23. available = true;
  24. consumed.signal(); // 发信号唤醒等待这个Condition的线程
  25. } finally {
  26. lock.unlock();
  27. }
  28. }
  29. public void consume() throws InterruptedException {
  30. lock.lock();
  31. try {
  32. if (!available) {
  33. consumed.await(); // 放弃lock进入睡眠
  34. }
  35. /* 吃苹果 */
  36. System.out.println("Apple consumed.");
  37. available = false;
  38. produced.signal(); // 发信号唤醒等待这个Condition的线程
  39. } finally {
  40. lock.unlock();
  41. }
  42. }
  43. }
package com.sishuok.es.test;import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;//生产/消费者模式public class Basket {Lock lock = new ReentrantLock(true);// 产生Condition对象Condition produced = lock.newCondition();Condition consumed = lock.newCondition();boolean available = false;AtomicInteger producedAwaitCounter = new AtomicInteger(0);public void produce() throws InterruptedException {lock.lock();try {if (available || producedAwaitCounter.get() > 0) {producedAwaitCounter.incrementAndGet();produced.await(); // 放弃lock进入睡眠producedAwaitCounter.decrementAndGet();}System.out.println("Apple produced.");available = true;consumed.signal(); // 发信号唤醒等待这个Condition的线程} finally {lock.unlock();}}public void consume() throws InterruptedException {lock.lock();try {if (!available) {consumed.await(); // 放弃lock进入睡眠}/* 吃苹果 */System.out.println("Apple consumed.");available = false;produced.signal(); // 发信号唤醒等待这个Condition的线程} finally {lock.unlock();}}}

java生产者消费者问题代码分析相关推荐

  1. java消费者模式_基于Java 生产者消费者模式(详细分析)

    生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相 ...

  2. java生产线消费者,基于Java 生产者消费者模式(详细分析)

    生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相 ...

  3. java 生产者消费者代码_Java生产者和消费者代码

    java 生产者消费者代码 This also helps us to understand the concept of synchronised multi-threading in java, ...

  4. 生产者消费者问题-代码详解(Java多线程)

    你好我是辰兮,很高兴你能来阅读,本篇是整理了Java多线程中常见的生产者消费者问题,也是面试手写代码的高频问题,分享获取新知,大家共同进步! 1.JAVA基础面试常考问题 : JAVA面试基础常考题汇 ...

  5. java 生产者消费者_基于JAVA的生产者消费者问题

    一.需求分析 为了更好地理解进程同步的机制和过程,决定设计实现生产者消费者问题的解决,以实现进程的同步控制. 题目描述:有n个生产者在生产产品,这些产品将提供给m个消费者去消费,为了使生产者和消费者能 ...

  6. delphi生产者消费者模式代码_并发设计模式:生产者-消费者模式,并发提高效率...

    生产者 - 消费者模式在编程领域的应用非常广泛,前面我们曾经提到,Java 线程池本质上就是用生产者 - 消费者模式实现的,所以每当使用线程池的时候,其实就是在应用生产者 - 消费者模式. 当然,除了 ...

  7. java 生产者消费者_Java多线程:线程间通信—生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是, 多个线程之间如何协作呢 ? 我们看一个 ...

  8. JAVA生产者消费者的实现

    春节回了趟老家,又体验了一次流水席,由于桌席多,导致上菜慢,于是在等待间,总结了一下出菜流程的几个特点: 1.有多个灶台,多个灶台都在同时做菜出来. 2.做出来的菜,会有专人用一个托盘端出来,每次端出 ...

  9. Java生产者 消费者模型的一种实现

    本文主要介绍java中生产者/消费者模式的实现,对java线程锁机制的一次深入理解. 生产者/消费者模型 生产者/消费者模型要保证,同一个资源在同一时间节点下只能被最多一个线程访问,这个在java中用 ...

最新文章

  1. PyTorch实现,GitHub star 4k+:这是微软开源的计算机视觉库
  2. codeforces 785D D. Anton and School - 2
  3. centos7安装pyenv
  4. android对skia的封装,Skia引擎API整理介绍(skia in Android 2.3 trunk)
  5. java万年历表怎么输出6_用Java编程输出万年历的功能实现
  6. 轮询调度算法 Round Robin
  7. 黄灯:一个农村儿媳眼中的乡村图景
  8. 01-初探MQ-MQ的三大使用场景:应用解耦、异步提速、削峰填谷
  9. 夏天什么适合做引流产品?夏天用什么东西做引流的产品
  10. LevelDB使用入门
  11. 新版白话空间统计(12):P值的表达以及空间统计上的特性
  12. 创业板公司相符如何经济转型
  13. Java日期格式2019-11-05T00:00:00转换标准日期
  14. 雄关漫道真如铁,而今迈步从头越.
  15. 阻抗、输入阻抗、特性阻抗……傻傻分不清楚
  16. (精品)运用PS的液化滤镜制作逼真的石头效果-PS滤镜教程
  17. 安装Office2010提示无法将数值写入注册表
  18. Mythtype对公式按章节自动编号和文中引用
  19. 博文推荐|通过 Apache Pulsar + ScyllaDB 构建实时聊天消息流
  20. 2008年05月16日

热门文章

  1. 强大而优雅,API 研发管理 EOLINKER 新版正式发布!
  2. js中如何删除json对象的某一个选项
  3. KVM安装、镜像创建(一)
  4. 使用 python 开发 Web Service
  5. hdu 4414 Finding crosses
  6. 页面添加复制代码功能
  7. vscode的 jsonp 配置文件
  8. Tcpdump抓包工具的使用
  9. Thinking in Java 源代码 source code 在IDEA上运行
  10. linux下搭建git服务器