java生产者消费者问题代码分析

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

 

具体代码:

Java代码 复制代码  收藏代码
  1. import java.util.concurrent.locks.Condition;   
  2.   
  3. import java.util.concurrent.locks.Lock;   
  4.   
  5. import java.util.concurrent.locks.ReentrantLock;   
  6.   
  7.   
  8. //生产/消费者模式   
  9.   
  10. public class Basket {   
  11.   
  12.     Lock lock = new ReentrantLock();   
  13.   
  14.   
  15.     // 产生Condition对象   
  16.   
  17.     Condition produced = lock.newCondition();   
  18.   
  19.     Condition consumed = lock.newCondition();   
  20.   
  21.     boolean available = false;   
  22.   
  23.   
  24.     public void produce() throws InterruptedException {   
  25.   
  26.         lock.lock();   
  27.   
  28.   
  29.         try {   
  30.   
  31.             if (available) {   
  32.   
  33.                 produced.await(); // 放弃lock进入睡眠   
  34.   
  35.             }   
  36.   
  37.   
  38.             System.out.println("Apple produced.");   
  39.   
  40.   
  41.             available = true;   
  42.   
  43.   
  44.             consumed.signal(); // 发信号唤醒等待这个Condition的线程   
  45.   
  46.         } finally {   
  47.   
  48.             lock.unlock();   
  49.   
  50.         }   
  51.   
  52.     }   
  53.   
  54.   
  55.     public void consume() throws InterruptedException {   
  56.   
  57.         lock.lock();   
  58.   
  59.   
  60.         try {   
  61.   
  62.             if (!available) {   
  63.   
  64.                 consumed.await(); // 放弃lock进入睡眠   
  65.   
  66.             }   
  67.   
  68.   
  69.             /* 吃苹果 */  
  70.   
  71.             System.out.println("Apple consumed.");   
  72.   
  73.   
  74.             available = false;   
  75.   
  76.   
  77.             produced.signal(); // 发信号唤醒等待这个Condition的线程   
  78.   
  79.         } finally {   
  80.   
  81.             lock.unlock();   
  82.   
  83.         }   
  84.   
  85.     }   
  86.   
  87. }  
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. //测试用类   
  5. public class ConditionTester {   
  6.   
  7.     public static void main(String[] args) throws InterruptedException {   
  8.         final Basket basket = new Basket();   
  9.   
  10.         // 定义一个producer   
  11.         Runnable producer = new Runnable() {   
  12.             public void run() {   
  13.                 try {   
  14.                     basket.produce();   
  15.                 } catch (InterruptedException ex) {   
  16.                     ex.printStackTrace();   
  17.                 }   
  18.             }   
  19.         };   
  20.   
  21.         // 定义一个consumer   
  22.         Runnable consumer = new Runnable() {   
  23.             public void run() {   
  24.                 try {   
  25.                     basket.consume();   
  26.                 } catch (InterruptedException ex) {   
  27.                     ex.printStackTrace();   
  28.                 }   
  29.             }   
  30.         };   
  31.   
  32.         // 各产生10个consumer和producer   
  33.         ExecutorService service = Executors.newCachedThreadPool();   
  34.   
  35.         for (int i = 0; i < 4; i++)   
  36.             service.submit(consumer);   
  37.   
  38.         Thread.sleep(2000 * 2);   
  39.   
  40.         for (int i = 0; i < 4; i++)   
  41.             service.submit(producer);   
  42.   
  43.         service.shutdown();   
  44.     }   
  45. }  
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.   
  3. import java.util.concurrent.atomic.AtomicInteger;   
  4. import java.util.concurrent.locks.Condition;   
  5.   
  6. import java.util.concurrent.locks.Lock;   
  7.   
  8. import java.util.concurrent.locks.ReentrantLock;   
  9.   
  10.   
  11. //生产/消费者模式   
  12.   
  13. public class Basket {   
  14.   
  15.     Lock lock = new ReentrantLock(true);   
  16.   
  17.   
  18. // 产生Condition对象   
  19.   
  20.     Condition produced = lock.newCondition();   
  21.   
  22.     Condition consumed = lock.newCondition();   
  23.   
  24.     boolean available = false;   
  25.     AtomicInteger producedAwaitCounter = new AtomicInteger(0);   
  26.   
  27.   
  28.     public void produce() throws InterruptedException {   
  29.   
  30.         lock.lock();   
  31.   
  32.         try {   
  33.   
  34.             if (available || producedAwaitCounter.get() > 0) {   
  35.                 producedAwaitCounter.incrementAndGet();   
  36.                 produced.await(); // 放弃lock进入睡眠   
  37.                 producedAwaitCounter.decrementAndGet();   
  38.             }   
  39.   
  40.             System.out.println("Apple produced.");   
  41.   
  42.   
  43.             available = true;   
  44.   
  45.   
  46.             consumed.signal(); // 发信号唤醒等待这个Condition的线程   
  47.   
  48.         } finally {   
  49.             lock.unlock();   
  50.         }   
  51.   
  52.     }   
  53.   
  54.   
  55.     public void consume() throws InterruptedException {   
  56.   
  57.         lock.lock();   
  58.   
  59.   
  60.         try {   
  61.   
  62.             if (!available) {   
  63.                 consumed.await(); // 放弃lock进入睡眠   
  64.             }   
  65.   
  66.             /* 吃苹果 */  
  67.   
  68.             System.out.println("Apple consumed.");   
  69.   
  70.   
  71.             available = false;   
  72.   
  73.             produced.signal(); // 发信号唤醒等待这个Condition的线程   
  74.         } finally {   
  75.             lock.unlock();   
  76.         }   
  77.   
  78.     }   
  79.   
  80. }  
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();}}}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/265926.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vb冒泡排序法流程图_VB算法-冒泡排序教案

1冒泡排序教学设计班级&#xff1a;高一一班授课教师&#xff1a;袁海军一、教案背景模块&#xff1a;算法与程序设计班级&#xff1a;高一(1)班课时数&#xff1a;1课时所用教材&#xff1a;华师大版《算法与程序设计》教师&#xff1a;袁海军二、教学设计1.教学目标知识与技能…

linux板级初始化

最近拿到了明远智睿 的EK314开发板&#xff0c;以前主要用2440&#xff0c;眼界过于狭隘&#xff0c;借此机会练习下。 http://lornyin.top/?p106 原文地址 首先看看它的板级文件 /arch/arm/mach-mx6/board-myimx6ek314.c 在他的末尾指定了map_io、init_irq、init_machine…

可以ping通 但ssh: connect to host 192.168.0.2 port 22: Connection refused

目录问题描述原因解决问题描述 自己在树莓派端通过SCP指令给电脑上ubuntu传输文件发现提示&#xff1a;ssh: connect to host 192.168.0.2 port 22: Connection refused&#xff0c;并且发现树莓派端是可以ping通ubuntu的。 原因 通过网上查新找到原因&#xff1a; SSH分客…

动态规划初步--数字三角形

数字三角形是一个由非负数组成的三角形&#xff0c;第n行有n个数&#xff0c;形如&#xff1a; 1 2 3 4 5 6 除最下行之外&#xff0c;每一行的左下和右下各有一个数&#xff0c;从第一行开始&#xff0c;向下&#xff0c;左或者右走一格&#xff0c;直到走到最后一行&#…

光影精灵5完全拆解全程图解_惠普光影精灵5值得买吗?惠普光影精灵5绿刃版游戏本深度拆解评测...

三星8GB DDR4 2666MHz内存还有一个小配件&#xff0c;虽然小&#xff0c;但绝对是最常用的&#xff0c;这就是无线模块。这款笔记本搭载的是Intel 9560NGW无线网卡&#xff0c;支持2.4GHz / 5GHz双频&#xff0c;最大传输速度可达1.73Gbps&#xff0c;并且集成蓝牙5.0版本&…

linux嵌入式贪吃蛇

目标&#xff1a;用游戏手柄控制贪吃蛇 硬件平台&#xff1a;imax6q 版本信息&#xff1a; arm-none-linux-gnueabi-gcc-4.8.3、 qt5.7.1、linux3.0.1 一、交叉编译tslib1.4 由于 imax6q是 armv7-a 构架&#xff0c;所以以后的编译我们都应编译出 armv7 平台的文件 编译参…

2.联邦模式配置---扩容,负载均衡

原理图 两个集群---目的&#xff1a;扩容 HA联邦模式解决了单纯HA模式的性能瓶颈&#xff08;主要指Namenode、ResourceManager&#xff09;&#xff0c;将整个HA集群划分为两个以上的集群&#xff0c;不同的集群之间通过Federation进行连接&#xff0c;使得HA集群拥有了横向扩…

树莓派交叉编译(PS交叉编译链下载安装、配置永久环境变量、带WiringPi库交叉编译、软链接)

目录一、本章概述二、交叉编译工具链的下载安装下载安装交叉编译链临时有效交叉编译链永久有效三、交叉编译的使用对比gcc与armgccPC端交叉编译发送到树莓派运行四、带WiringPi库的交叉编译如何处理复制树莓派上的WiringPi库到主机软硬链接交叉编译一、本章概述 下面将详细介绍…

海量数据处理分析(部分)

2019独角兽企业重金招聘Python工程师标准>>> 1. 海量数据处理分析 原文地址&#xff1a; http://blog.csdn.net/DaiZiLiang/archive/2006/12/06/1432193.aspx 笔者在实际工作中&#xff0c;有幸接触到海量的数据处理问题&#xff0c;对其进行处理是一项艰巨而复…

android p wifi一直在扫描_在Android上的每次WiFi扫描之间我应该使用什么时间间隔?...

我需要定期执行Wifi扫描.当时间间隔设置为1-2秒时,我遇到了问题.好像我没有得到任何ScanResult.是否有最短的时间设置,以便WifiManager能够执行成功的WiFi扫描&#xff1f;这是代码.我正在使用服务进行Wifi扫描&#xff1a;public class WifiScanning extends Service{private …

uboot2015–启动流程分析 imx6q

最近项目原因&#xff0c;要在uboot中增加内核验校和内核损坏修复功能&#xff0c;所以需要回头看看uboot。这次选择了uboot2015来进行分析 uboot是明远睿智提供的。 下载地址 链接&#xff1a;https://pan.baidu.com/s/13SuRii3WTqvFTNIsSS9GAg 密码&#xff1a;65zz 环境&…

树莓派内核开发准备(内核源码获取、启动过程、源码目录树)

目录1.交叉编译工具的安装2.内核源码获取3.嵌入式设备带操作系统的启动过程扫盲4.Linux内核源码树扫盲1.内核源码简介2.Linux内核源代码目录树结构tree指令查看内核源码目录树1.交叉编译工具的安装 参照我之前的笔记 2.内核源码获取 下载哪个版本取决于树莓派的版本&#xf…

linux修改文件句柄数生效_修改Linux的open files参数是,立即生效,无需重启

通过命令ulimit -a查看的open files参数的修改&#xff1a;core file size (blocks, -c) 0data seg size (kbytes, -d) unlimitedscheduling priority (-e) 0file size (blocks, -f) unlimitedpending signals (…

柯乐义猜数字游戏

游戏规则&#xff1a;柯乐义请您玩猜数字游戏。后台已经随机生成了一个100到999之间的数字。如果您能在10次之内猜出这个数字&#xff0c;则游戏成功&#xff0c;否则失败。请开始吧。 SilverLight 猜数字游戏&#xff1a;http://keleyi.com/keleyi/phtml/silverlight/ 一次猜数…

fsdisk 分区

芯片主控&#xff1a;imx6q http://lornyin.top/?p545 昨天在做一个linux嵌入式项目时要修改板子的分区&#xff0c;查看了ucl2.xml &#xff08;mfgtool&#xff09;文件后&#xff0c;找到了他的分区脚本 #!/bin/sh# partition size in MB BOOT_ROM_SIZE10# call sfdisk …

树莓派Linux内核源码配置、编译、挂载(boot/kernal/根文件)、开启新内核

目录一、树莓派Linux源码配置(适合树莓派)总体概述配置的三种方式1.照搬厂家的配置&#xff08;使用这种方式&#xff09;2.参考厂家的配置&#xff08;感受一下&#xff09;3.完全自主配置&#xff08;需要一定工作经验&#xff09;二、树莓派Linux内核编译三、树莓派挂载新内…

xshell连接linux出现乱码

今天用Xshell连接linux&#xff0c;查看一个脚本&#xff0c;里面有中文写的注解&#xff0c;出现了乱码&#xff0c;所以记录一下&#xff0c;以便下次用到&#xff0c;也可以帮助遇到同样问题的小伙伴。 以下是乱码的截图&#xff1a; 我们可以照着下面的方式更改编码&#x…

阡陌路-车行天下之汽车基础知识

汽车基础知识 1、什么是ABS   ABS是Anti-LockBrakeSystem的英文缩写&#xff0c;翻译过来可以叫做“刹车防抱死系统”。在没有ABS时&#xff0c;如果紧急刹车一般会使轮胎 抱死&#xff0c;由于抱死之后轮胎与地面是滑动摩擦&#xff0c;所以刹车的距离会变长。如果前轮锁死…

java版本号分段比较_Java实现比较版本号

涉及到客户端的系统中经常需要用到比较版本号的功能&#xff0c;但是比较版本号又不能完全按照字符串比较的方式去用compareTo之类的方法&#xff1b;这就需要我们总结版本号的通用规则&#xff0c;设计一个比较算法并封装成通用方法来使用&#xff1a;通常版本号如&#xff1a…

win10 重置串口

最近想起了玩玩51单片机&#xff0c;回味下&#xff0c;发现以前板子送人了&#xff0c;于是随便捡了一个下载器来给AT89S52下程序&#xff0c;下载器是通过串口和电脑通讯的, 可是要求串口端口号不能大于10&#xff0c;我的串口号都特别大&#xff0c;于是尝试到设备管理器里修…