java生产者消费者问题代码分析
作者要的是一个生产者生成,接着必须有一个消费者消费,那这不是需要单线程吗?或者使用1个大小的阻塞队列。所以只谈论问题本身,不谈论好不好。
具体代码:
- 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();
- }
- }
- }
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();}}}
- 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();
- // 定义一个producer
- Runnable producer = new Runnable() {
- public void run() {
- try {
- basket.produce();
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- }
- }
- };
- // 定义一个consumer
- Runnable consumer = new Runnable() {
- public void run() {
- try {
- basket.consume();
- } catch (InterruptedException ex) {
- ex.printStackTrace();
- }
- }
- };
- // 各产生10个consumer和producer
- ExecutorService 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();
- }
- }
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进入睡眠
}
- 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();
- }
- }
- }
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生产者消费者问题代码分析相关推荐
- java消费者模式_基于Java 生产者消费者模式(详细分析)
生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相 ...
- java生产线消费者,基于Java 生产者消费者模式(详细分析)
生产者消费者模式是多线程中最为常见的模式:生产者线程(一个或多个)生成面包放进篮子里(集合或数组),同时,消费者线程(一个或多个)从篮子里(集合或数组)取出面包消耗.虽然它们任务不同,但处理的资源是相 ...
- java 生产者消费者代码_Java生产者和消费者代码
java 生产者消费者代码 This also helps us to understand the concept of synchronised multi-threading in java, ...
- 生产者消费者问题-代码详解(Java多线程)
你好我是辰兮,很高兴你能来阅读,本篇是整理了Java多线程中常见的生产者消费者问题,也是面试手写代码的高频问题,分享获取新知,大家共同进步! 1.JAVA基础面试常考问题 : JAVA面试基础常考题汇 ...
- java 生产者消费者_基于JAVA的生产者消费者问题
一.需求分析 为了更好地理解进程同步的机制和过程,决定设计实现生产者消费者问题的解决,以实现进程的同步控制. 题目描述:有n个生产者在生产产品,这些产品将提供给m个消费者去消费,为了使生产者和消费者能 ...
- delphi生产者消费者模式代码_并发设计模式:生产者-消费者模式,并发提高效率...
生产者 - 消费者模式在编程领域的应用非常广泛,前面我们曾经提到,Java 线程池本质上就是用生产者 - 消费者模式实现的,所以每当使用线程池的时候,其实就是在应用生产者 - 消费者模式. 当然,除了 ...
- java 生产者消费者_Java多线程:线程间通信—生产者消费者模型
一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是, 多个线程之间如何协作呢 ? 我们看一个 ...
- JAVA生产者消费者的实现
春节回了趟老家,又体验了一次流水席,由于桌席多,导致上菜慢,于是在等待间,总结了一下出菜流程的几个特点: 1.有多个灶台,多个灶台都在同时做菜出来. 2.做出来的菜,会有专人用一个托盘端出来,每次端出 ...
- Java生产者 消费者模型的一种实现
本文主要介绍java中生产者/消费者模式的实现,对java线程锁机制的一次深入理解. 生产者/消费者模型 生产者/消费者模型要保证,同一个资源在同一时间节点下只能被最多一个线程访问,这个在java中用 ...
最新文章
- PyTorch实现,GitHub star 4k+:这是微软开源的计算机视觉库
- codeforces 785D D. Anton and School - 2
- centos7安装pyenv
- android对skia的封装,Skia引擎API整理介绍(skia in Android 2.3 trunk)
- java万年历表怎么输出6_用Java编程输出万年历的功能实现
- 轮询调度算法 Round Robin
- 黄灯:一个农村儿媳眼中的乡村图景
- 01-初探MQ-MQ的三大使用场景:应用解耦、异步提速、削峰填谷
- 夏天什么适合做引流产品?夏天用什么东西做引流的产品
- LevelDB使用入门
- 新版白话空间统计(12):P值的表达以及空间统计上的特性
- 创业板公司相符如何经济转型
- Java日期格式2019-11-05T00:00:00转换标准日期
- 雄关漫道真如铁,而今迈步从头越.
- 阻抗、输入阻抗、特性阻抗……傻傻分不清楚
- (精品)运用PS的液化滤镜制作逼真的石头效果-PS滤镜教程
- 安装Office2010提示无法将数值写入注册表
- Mythtype对公式按章节自动编号和文中引用
- 博文推荐|通过 Apache Pulsar + ScyllaDB 构建实时聊天消息流
- 2008年05月16日