所谓的生产者消费者问题,就是存在生产者和消费者两个线程,当仓库还没满的时候,生产者可以生产,当仓库没空的时候,消费者可以取走商品。

我们用实例说话:

下面,我们创建几个类:

1、消费者--主要负责消费商品

2、生产者--负责生产商品

3、仓库--存储商品,用一个变量表示仓库里面商品的数量。

首先,我们先用一个程序来引出我们的话题:
package com.huai.test;public class CPThreadTest {public static void main(String[] args) {Customer c = new Customer();Product p = new Product();Thread tc = new Thread(c);Thread tp = new Thread(p);tc.start();tp.start();}
}class Customer implements Runnable {public void doConsume() {if (!Ware.isEmpty()) {Ware.productCount--;System.out.println("consume one, left " + Ware.productCount);}}@Overridepublic void run() {while (true) {doConsume();}}
}class Product implements Runnable {public void doProduct() {if (!Ware.isFull()) {Ware.productCount++;System.out.println("product one, left " + Ware.productCount);}}@Overridepublic void run() {while (true) {doProduct();}}
}class Ware {public static int productCount = 0;public static int max = 100;public static boolean isFull() {return productCount >= max;}public static boolean isEmpty() {return productCount <= 0;}}

运行结果是:运行结果非常奇怪:从下面看出,消费者消费之后,仓库里面没有产品了,可是生产者竟然说还剩下100个。为什么会出现这么奇怪的现象呢?多线程共享相同数据造成的。为了避免这样的问题,我们应该怎么改进我们的程序呢?请看下面:

解决方案1:

思路:把Ware这个资源(这里我把Ware类称为资源)实现同步互斥。当生产者获得仓库的钥匙的时候,消费者就不能进去取走商品了,反之,当消费者获得仓库的钥匙正在消费商品的时候,生产者就不能生产并存入商品了。

package com.huai.test;public class CPThreadTest {public static void main(String[] args) {Customer c = new Customer();Product p = new Product();Thread tc = new Thread(c);Thread tp = new Thread(p);tc.start();tp.start();}
}class Customer implements Runnable{public void doConsume(){synchronized (Ware.class) {if(!Ware.isEmpty()){Ware.productCount--;System.out.println("consume one, left "+Ware.productCount);}}}@Overridepublic void run() {while(true){doConsume();}}
}class Product implements Runnable{public void doProduct(){synchronized (Ware.class) {if(!Ware.isFull()){Ware.productCount++;System.out.println("product one, left "+Ware.productCount);}}}@Overridepublic void run() {while(true){doProduct();}}
}class Ware{public static int productCount = 0;public static int max = 100;public static boolean isFull(){return productCount >= max;}public static boolean isEmpty(){return productCount <= 0;}}

部分运行结果:

consume one, left 22
consume one, left 21
consume one, left 20
consume one, left 19
consume one, left 18
consume one, left 17
consume one, left 16
consume one, left 15
consume one, left 14
consume one, left 13
consume one, left 12
consume one, left 11
consume one, left 10
consume one, left 9
consume one, left 8
consume one, left 7
consume one, left 6
consume one, left 5
consume one, left 4
consume one, left 3
consume one, left 2
consume one, left 1
consume one, left 0
product one, left 1
product one, left 2
product one, left 3
product one, left 4
product one, left 5
product one, left 6
product one, left 7
product one, left 8
product one, left 9
product one, left 10
product one, left 11
product one, left 12
解决方案2:

思路:把生产和消费这两个动作放到仓库里面,原理和上面的差不多,只是同步互斥的方式不一样。

注:在Ware中,当有一个线程正在运行synchronized方法的时候,其他申明了synchronized的方法也不能被其他线程访问,但可以访问非synchronized申明的方法。怎么验证?你可以把下面例子中的一个synchronized去掉,就会发现打印出来的结果,相邻两个的数字相差不全是1.

package com.huai.test;public class CPThreadTest {public static void main(String[] args) {Customer c = new Customer();Product p = new Product();Thread tc = new Thread(c);Thread tp = new Thread(p);tc.start();tp.start();}
}class Customer implements Runnable {@Overridepublic void run() {while (true) {Ware.doConsume();}}
}class Product implements Runnable {@Overridepublic void run() {while (true) {Ware.doProduct();}}
}class Ware {public static int productCount = 0;public static int max = 100;public static boolean isFull() {return productCount >= max;}public static boolean isEmpty() {return productCount <= 0;}public static synchronized void doProduct(){if (!Ware.isFull()) {Ware.productCount++;System.out.println("product one, left " + Ware.productCount);}}public static synchronized void doConsume(){if (!Ware.isEmpty()) {Ware.productCount--;System.out.println("consume one, left " + Ware.productCount);}}
}

java线程模拟生产者消费者问题相关推荐

  1. Java线程实现生产者—消费者模式

    在这里插入代码片# Java 线程实现生产者-消费者模式 ##思路:实现类似消费者生产者线程之间通讯的功能,每创建一个工人,就让这个工人干活,干一段时间,工人自动消失,然后又去创建一个工人干活: 代码 ...

  2. JAVA线程之生产者消费者问题

    复习下JAVA线程基础知识: 1.线程的状态: 创建状态:创建了线程对象,此时线程有了相应的内存空间和其他资源,但处于不可运行状态. 就绪状态:线程对象调用start()方法启动线程,进入就绪状态,此 ...

  3. Java 线程池 +生产者消费者+MySQL读取300 万条数据

    1.1需求 数据库300 万条用户数据 ,遍历获取所有用户, 各种组合关联, 获取到一个新的json ,存到redis 上. 1.2 难点 数据库比较多, 不可能单线程查询所有的数据到内存. 1.3解 ...

  4. Java线程实现生产者消费者模式

    1 什么是生产者消费者模式 想一个现实生活中的例子,啤酒商---超市---消费者也就是我们,啤酒商生产了啤酒,然后将啤酒销售给了超市,我们消费之又会到超市将啤酒买回来自己喝,那么啤酒商和消费者之间是什 ...

  5. Java 线程实例二(终止线程、生产者/消费者问题、获取线程状态、获取所有线程、查看线程优先级、中断线程)

    终止线程 Java中原来在Thread中提供了stop()方法来终止线程,但这个方法是不安全的,所以一般不建议使用. 本文向大家介绍使用interrupt方法中断线程. 使用interrupt方法来终 ...

  6. java线程之生产者与消费者

    预习java线程的三种创建方式 package com.bj.thread;import java.util.concurrent.*;/*** @FileName: TestThread* @Rem ...

  7. 线程同步 生产者消费者 java_Java线程同步:生产者-消费者 模型(代码示例)

    public class ThreadSyn { public static void main(String[] args) { new ThreadSyn(); } public ThreadSy ...

  8. python模拟生产者消费者进程可视化tkinter

    python模拟生产者消费者进程可视化tkinter 模拟内容要求 一.效果截图 二.代码实现 说明 模拟内容要求 利用C语言或JAVA语言或C++语言(手段不限),验证生产者与消费问题的过程. 一. ...

  9. C++编程模拟生产者消费者模型

    生产者消费者问题是操作系统中典型的进程同步互斥问题,(英语:Producer-Consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同 ...

最新文章

  1. Dialog 带白色的边的处理方法
  2. 使用E-MapReduce服务将Kafka数据导入OSS
  3. math-neon基于NEON指令的数学库
  4. 从一个疯狂下载者变成一个学习者
  5. ADO.NET中的五个主要对象
  6. python 持续集成工具_持续集成工具: Jenkins学习
  7. ASP.NET Core 依赖注入-集成 Autofac
  8. 高等数学下-赵立军-北京大学出版社-题解-练习11.1
  9. linq查询不包含某个值的记录_mysql基本知识点梳理和查询优化
  10. 腾讯二面:引入RabbitMQ后,你如何保证全链路数据100%不丢失 ?
  11. web 开发安全性问题
  12. Pandas处理缺失数据
  13. 闲置笔记本的群晖NAS初体验
  14. linux为360路由器刷机,[详细]360路由器刷openwrt、不死uboot、双系统 、wifi中继
  15. 06_XML的写入_dom4j添加、删除、修改Xml文件内容
  16. 按键精灵sayString不生效
  17. 姿态估计1-02:HR-Net(人体姿态估算)-官方模型训练测试-报错解决
  18. Teigha开发读取CAD文字信息出现偏移
  19. Flash分模块开发,Flash分模块加载,以及使用Flex经行游戏开发!
  20. 【web3j】java调用链上合约里的方法

热门文章

  1. MATLAB把型线图画静水力曲线,静水力曲线图
  2. java hibernate configuration 获取_1 Hibernate Configuration 配置
  3. python生成epub文件_python在内存中生成Zip文件!
  4. 【c语言】整型数据的溢出
  5. windows c 操作mysql_windows下c/C++操作Mysql的一些总结(绝对精华,不要错过)
  6. Oracle中INSTR和SUBSTR的用法
  7. asp.net core系列 38 WebAPI 返回类型与响应格式--必备
  8. angular cli全局版本大于本地版本 把本地版本升级方式
  9. 惠普企业第三财季净利润23亿美元 同比增长914%
  10. 线程池ThreadPoolExecutor