生产者消费者两种实现:wait/notifyAll和Lock/Condition
1.wait/notifyAll
/**
* 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法,
* 能够支持2个生产者线程以及10个消费者线程的阻塞调用
*
* 使用wait和notify/notifyAll来实现
*
* @author cx
*/
package com.chanx.demo.example.c_021; import java.util.LinkedList;
import java.util.concurrent.TimeUnit; public class MyContainer1<T> {
final private LinkedList<T> lists = new LinkedList<>();
final private int MAX = 10; //最多10个元素
private int count = 0; public synchronized void put(T t) {
while(lists.size() == MAX) { //想想为什么用while而不是用if?
try {
this.wait(); //effective java
} catch (InterruptedException e) {
e.printStackTrace();
}
} lists.add(t);
++count;
this.notifyAll(); //通知消费者线程进行消费
} public synchronized T get() {
T t = null;
while(lists.size() == 0) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
t = lists.removeFirst();
count --;
this.notifyAll(); //通知生产者进行生产
return t;
} public static void main(String[] args) {
MyContainer1<String> c = new MyContainer1<>();
//启动消费者线程
for(int i=0; i<10; i++) {
new Thread(()->{
for(int j=0; j<5; j++) System.out.println(c.get());
}, "c" + i).start();
} try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} //启动生产者线程
for(int i=0; i<2; i++) {
new Thread(()->{
for(int j=0; j<25; j++) c.put(Thread.currentThread().getName() + " " + j);
}, "p" + i).start();
}
}
}
2.Lock/Condition
/**
* 面试题:写一个固定容量同步容器,拥有put和get方法,以及getCount方法,
* 能够支持2个生产者线程以及10个消费者线程的阻塞调用
*
* 使用wait和notify/notifyAll来实现
*
* 使用Lock和Condition来实现
* 对比两种方式,Condition的方式可以更加精确的指定哪些线程被唤醒
*
* @author cx
*/
package com.chanx.demo.example.c_021; import java.util.LinkedList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class MyContainer2<T> {
final private LinkedList<T> lists = new LinkedList<>();
final private int MAX = 10; //最多10个元素
private int count = 0; private Lock lock = new ReentrantLock();
private Condition producer = lock.newCondition();
private Condition consumer = lock.newCondition(); public void put(T t) {
try {
lock.lock();
while(lists.size() == MAX) { //想想为什么用while而不是用if?
producer.await();
} lists.add(t);
++count;
consumer.signalAll(); //通知消费者线程进行消费
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
} public T get() {
T t = null;
try {
lock.lock();
while(lists.size() == 0) {
consumer.await();
}
t = lists.removeFirst();
count --;
producer.signalAll(); //通知生产者进行生产
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
return t;
} public static void main(String[] args) {
MyContainer2<String> c = new MyContainer2<>();
//启动消费者线程
for(int i=0; i<10; i++) {
new Thread(()->{
for(int j=0; j<5; j++) System.out.println(c.get());
}, "c" + i).start();
} try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
} //启动生产者线程
for(int i=0; i<2; i++) {
new Thread(()->{
for(int j=0; j<25; j++) c.put(Thread.currentThread().getName() + " " + j);
}, "p" + i).start();
}
}
}
生产者消费者两种实现:wait/notifyAll和Lock/Condition的更多相关文章
- 生产者消费者模式-Java实现
感知阶段 随着软件业的发展,互联网用户的日渐增多,并发这门艺术的兴起似乎是那么合情合理.每日PV十多亿的淘宝,处理并发的手段可谓是业界一流.用户访问淘宝首页的平均等待时间只有区区几秒,但是服务器所处理 ...
- Java多线程_生产者消费者模式1
生产者消费者模型 具体来讲,就是在一个系统中,存在生产者和消费者两种角色,他们通过内存缓冲区进行通信,生产者生产消费者需要的资料,消费者把资料做成产品.生产消费者模式如下图.(图片来自网络 ...
- 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)
参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...
- Java实现多线程生产者消费者模式的两种方法
生产者消费者模式:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据.生产者生产一个,消费者消费一个,不断循环. 第一种实现方法,用BlockingQueue阻塞队 ...
- 生产者-消费者模型的3种Java实现:synchronized,signal/notifyAll及BlockingQueue
我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3555111.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...
- java 多线程并发系列之 生产者消费者模式的两种实现
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题.该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度. 为什么要使用生产者和消费者模式 在线程世界里,生产者就是生产数据 ...
- Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
- 生产者消费者问题Java三种实现
生产者-消费者Java实现 2017-07-27 1 概述 生产者消费者问题是多线程的一个经典问题,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品. 解决生产者/ ...
- 多线程之线程间协作的两种方式:wait、notify、notifyAll和Condition
Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...
随机推荐
- 福大软工1816 · 第三次作业 - 结对项目Salty Fish原型图
SALTY FISH原型图 LINKS IMPORT to LIST FOCUS TRENDS ANALYSE NIGHT
- Linux文件系统命令 touch/rm
命令:touch 功能:创建文件,后接相对路径或者绝对路径 eg: touch ./ren/jin/gui.txt 命令:rm 功能:删除文件,当删除的是目录的时候要加-R参数进行递归删除. eg: ...
- marquee 的浏览器兼容性
marquee 在IE,firefox,chrome ,safari下都能正常的实现走马灯效果,兼容性没有问题 并且两个关键属性scrollamount(滚动速度)direction(滚动方向) 所有 ...
- day 51
一 window对象 window 对象表示一个浏览器窗口. 在客户端 JavaScript 中,Window 对象是全局对象,所有的表达式都在当前的环境中计算.也就是说,要引用当前窗口根本不需要特殊 ...
- idea打包 - 可执行jar包
需求:有一个基于SpringBoot的socket服务端程序,实现了对消息的接收.发送并行操作.此时想要将其构建成可执行的Jar包,执行 java -jar xx.jar后能够进行消息的收发. 分析: ...
- 六、在U-boot中让LCD填充纯色
1. 编译U-boot 准备好U-boot压缩包urbetter-u-boot-1.1.6-v1.0.tgz,输入命令:tar -xvf urbetter-u-boot-1.1.6-v1.0.tgz ...
- chromium ①
Chrome源码剖析 [序] && [一] 1. 它是如何利用多进程(其实也会有多线程一起)做并发的, 进程间通信,进程的开销:2. 做为一个后来者,它的扩展能力如何 3. 它的整体框 ...
- winform datatable 或datagridview中添加列
DataGridViewCheckBoxColumn dg = new DataGridViewCheckBoxColumn(); dg.HeaderText = "选择"; dg ...
- web(四)html表单类标签
表单类标签 操作者用于输入信息,并将信息提交给服务器的标签集合. 表单标签介绍 form标签:表单元素(其余标签)标签的容器标签 input标签:用于用户信息输入的标签. button标签:按钮标签. ...
- Linux关闭透明大页配置
一.为何要关闭透明大页 A--MOS获取 . #翻译 由于透明超大页面已知会导致意外的节点重新启动并导致RAC出现性能问题,因此Oracle强烈建议禁用透明超大页面. 另外,即使在单实例数据库环境 ...