7.生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信)
/*
* 生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信)
* */
public class TestProductorAndConsumerForLock {
public static void main(String[] args) {
WareHouse wareHouse = new WareHouse();
Productor pd1 = new Productor(wareHouse);
Consumer cs1 = new Consumer(wareHouse); new Thread(pd1, "消费者1").start();
new Thread(cs1, "生产者1").start();
// 若有多个 生产者消费者,可能会产生虚假唤醒(缺货了,多个生产线程等待,唤醒时,这些生产线程同时醒来,对数据进行操作,这种问题叫做虚假唤醒)
// 解决办法:wait方法 尽量 使用在循环中,被唤醒之后,再去判断是否符合条件(库存是否达到上限),不符合条件
// 继续等待(等待消费者去消费商品),直到 条件符合(库存有空闲)
new Thread(pd1, "消费者2").start();
new Thread(cs1, "生产者2").start();
}
} // 仓库
class WareHouse {
// 商品数量
private int products = 0;
private ReentrantLock lock = new ReentrantLock();
//使用 Condition 的前提是 使用 Lock 同步锁,Condition 实例 实质上被绑定到一个锁上
private Condition condition = lock.newCondition(); public void set() {
lock.lock();
try {
while (products >= 1) {
System.out.println("商品库存满了");
try {
// 如果商品满了,阻塞线程,等待消费者线程消费完成后唤醒,
condition.await(); //相当于(Object.awatit() 但是功能更强大)
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("生产了商品,剩余库存" + ++products);
condition.signalAll(); //相当于 (Object.notifyAll,功能更强大)
} finally {
lock.unlock();
} } public void get() {
lock.lock();
try {
while (products <= 0) {
System.out.println("商品库存没了");
try {
// 如果商品没了,阻塞线程,等待生产者线程生产完成后唤醒,
condition.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("消费了商品,剩余库存" + --products);
condition.signalAll();
} finally {
lock.unlock();
} }
} // 生产者
class Productor implements Runnable {
private WareHouse wareHouse; public Productor(WareHouse wareHouse) {
this.wareHouse = wareHouse;
} @Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
wareHouse.get();
}
} } // 消费者
class Consumer implements Runnable {
private WareHouse wareHouse; public Consumer(WareHouse wareHouse) {
this.wareHouse = wareHouse;
} @Override
public void run() {
for (int i = 0; i < 20; i++) { wareHouse.set();
}
} }
7.生产者消费者 案例 (使用Lock 同步锁 方式,使用Condition完成线程之间的通信)的更多相关文章
- Condition线程通信_生产者消费者案例
①Condition 接口描述了可能会与锁有关联的条件变量. 这些变量在用 法上与使用 Object.wait 访问的隐式监视器类似,但提供了更强大的 功能. 需要特别指出的是,单个 Lock 可能与 ...
- GUC-13 生产者消费者案例
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.uti ...
- JUC--Callable 以及Lock同步锁
/** * 一.创建执行线程的方式三:实现Callable接口.相较于实现Runnable接口方式,方法可以有返回值,并且可以抛出异常 * 二.callable 需要FutureTask实现类的支持. ...
- Lock同步锁
Lock同步锁 一.前言 在Java 5.0 之前,协调共享对象的访问时可以使用的机制只有synchronized 和volatile .Java 5.0 后增加了一些新的机制,但并不是一种替代内置锁 ...
- (转)生产者/消费者问题的多种Java实现方式
参考来源:http://blog.csdn.net/monkey_d_meng/article/details/6251879/ 生产者/消费者问题的多种Java实现方式 实质上,很多后台服务程序并发 ...
- java之线程(线程的创建方式、java中的Thread类、线程的同步、线程的生命周期、线程之间的通信)
CPU:10核 主频100MHz 1核 主频 3GHz 那么哪一个CPU比较好呢? CPU核不是越多越好吗?并不一定.主频用于衡量GPU处理速度的快慢,举个例子10头牛运送货物快还是1架飞机运 ...
- Lock同步锁--线程同步
Lock-同步锁 Lock是java5提供的一个强大的线程同步机制--通过显示定义同步锁对象来实现同步.Lock可以显示的加锁.解锁.每次只能有一个线程对lock对象加锁. Lock有ReadLock ...
- 深入分析 Java Lock 同步锁
前言 Java 的锁实现,有 Synchronized 和 Lock.上一篇文章深入分析了 Synchronized 的实现原理:由Java 15废弃偏向锁,谈谈Java Synchronized 的 ...
- Java并发编程之Lock(同步锁、死锁)
这篇文章是接着我上一篇文章来的. 上一篇文章 同步锁 为什么需要同步锁? 首先,我们来看看这张图. 这是一个程序,多个对象进行抢票. package MovieDemo; public class T ...
随机推荐
- float和int转换
http://blog.sina.com.cn/s/blog_5c6f79380101bbrd.html https://blog.csdn.net/ganxingming/article/detai ...
- Jmeter与BlazeMeter使用 录制导出jmx
本文链接:https://blog.csdn.net/weixin_38250126/article/details/82629876JMeter 的脚本录制,除了自带的HTTP代理服务器以外,被大家 ...
- 使用json_encode编码中文返回null的解决方案
在gbk的程序中,直接使用json_encode编码包含中文字符的数组,将会返回null. 解决方法: 1.把程序文件编码改为utf8 2.使用mb_convert_encoding把编码转换为utf ...
- Python-Web-数据库-mongodb
理念: ----无创建数据库方法,使用即创建 ----里面无数据,即数据库不存在 ----数据库有表,表里有一条数据,则数据库存在 ----表数据为JSON格式[{‘name’:’lisi’,’age ...
- 机器学习算法K-NN的一个使用实例:预测一个人是否患有糖尿病 (KNN-Predict whether a person will have diabetes or not )
学习中...不断更新. 在糖尿病人的数据库中有几列是不能为0的 比如葡萄糖 胰岛素 身体指数和皮肤厚度.所以在数据预处理阶段需要对这些列的数据进行替换. remeber we did 12 minus ...
- UIPath工具里面如何入力一览里面的数据
问题描述: UIpath工具如何在网页里面入力一览多条的数据.例如:某个公司里面在自己的内部员工管理的软件里面手动入力公司员工的所有信息之后反馈到数据库当中. 解决方法: UIpath工具来入力数据, ...
- solr后台【web页面】增删改查
就是在下面这个页面操作 增加 {"id":"2", "name": "添加"} 查询 id:2 修改 {"id ...
- Nginx 413 Request Entity Too Large
用户上传图片的时候,报错. 发现,原来是图片太大导致. 咦?后台配置图片支持5M啊? 哦!原来是Nginx配置问题. Nginx默认支持1M的POST数据! 修改Nginx配置! 修改nginx.co ...
- SrpingBoot入门到入坟02-HelloWorld的细节和初始自动配置
关于SpringBoot的第一个HelloWorld的一些细节: 1.父项目 首先查看项目中的pom.xml文件 文件中有个父项目,点进去则: 它里面也有一个父项目,再点进去: 可以发现有很多的依赖版 ...
- PHP和Memcached - Memcached的安装
1.现有扩展对比 memcache memcached 实现方式 原生 局域libmemcached的类库,性能高 编程方式 面向过程.对象 面向对象 CAS命令 NO YES php7 NO Y ...