java多线程(7)---Condition
Condition
一、Condition概述
在线程的同步时可以使一个线程阻塞而等待一个信号,同时放弃锁使其他线程可以能竞争到锁。
在synchronized中我们可以使用Object的wait()和notify方法实现这种等待和唤醒。
在Lock可以实现相同的功能就是通过Condition。Condition中的await()和signal()/signalAll()就相当于Object的wait()和notify()/notifyAll()。
除此之外,Condition还是对多线程条件进行更精确的控制。notify()是唤醒一个线程,但它无法确认是唤醒哪一个线程。 但是,通过Condition,就能明确的指定唤醒读线程。
二、Condition和Object案例对比
案例说明:生成者在仓库满时,进入等待状态,同时唤醒消费者线程,消费者在仓库为空时,进入等待。同时唤醒生产者线程。
1、采用await()和signal()方式
(1)测试类
public class ConditionLockTest { public static void main(String[] args){ //相当于仓库
Depot depot=new Depot(); //创建两个生产者一个消费者
Producer producer1=new Producer(depot);
Producer producer2=new Producer(depot);
Consumer consumer1=new Consumer(depot); //采用线程池方式
Executor executors=Executors.newFixedThreadPool(5);
executors.execute(producer1);
executors.execute(producer2);
executors.execute(consumer1);
}
} //生产者
class Producer implements Runnable { Depot depot;
public Producer(Depot depot){
this.depot=depot;
}
public void run(){
while(true){
depot.prod();
}
}
} //消费者
class Consumer implements Runnable{ Depot depot;
public Consumer(Depot depot){
this.depot=depot;
}
public void run(){
while(true){
depot.consum();
}
}
}
(2)仓库类
public class Depot {
//初始仓库为0,最大为10,超过10生产者停止生产
private int size;
private int maxSize=10; private Condition prodCondition;
private Condition consumCondition; private Lock lock;
public Depot(){ this.size=0;
this.lock=new ReentrantLock();
//可以看出Condition对象依赖于Lock锁
this.prodCondition=this.lock.newCondition();
this.consumCondition=this.lock.newCondition();
} /*
* 生产者生产方法
*/
public void prod(){ lock.lock();
try{
//如果生产超过max值,则生产者进入等待
while(size+1>maxSize){
try {
System.out.println(Thread.currentThread().getName()+"生产者进入等待状态");
prodCondition.await();
} catch (Exception e) {
e.printStackTrace();
}
}
size+=1;
System.out.println(Thread.currentThread().getName()+" 生产了一个 "+1+" 总共还有 "+size); //唤醒消费者线程
consumCondition.signal(); }finally {
lock.unlock();
}
} /*
* 消费者消费方法
*/
public void consum(){ lock.lock();
try{
//如果当前大小减去要消费的值,如果小于0的话,则进入等待
while(size-1<0){
try {
System.out.println(Thread.currentThread().getName()+" 消费者进入等待状态");
consumCondition.await(); } catch (Exception e) {
e.printStackTrace();
}
} size-=1;
System.out.println(Thread.currentThread().getName()+" 消费者消费了 "+1+" 个,总共还有 "+size);
//唤醒生产者线程
prodCondition.signal();
}finally {
lock.unlock();
}
}
}
运行结果(截取部分图)
根据结果分析可以得出:
生产者生产产品,当超过10个,生产者会处于等待状态,直到消费者消费者消费了一个产品,生产者才会重新唤醒。
2、采用wait()和notifyAll()方法
(1)仓库类代码(测试类代码不变)
public class Depot {
//初始仓库为0,最大为10,超过10生产者停止生产
private int size;
private int maxSize=10; public Depot(){
this.size=0;
} /*
* 生产者生产方法
*/
public synchronized void prod(){ try{
//如果生产超过max值,则生产者进入等待
while(size+1>maxSize){
try {
//采用wait方法
wait();
System.out.println(Thread.currentThread().getName()+"生产者进入等待状态");
} catch (Exception e) {
e.printStackTrace();
}
} size+=1;
System.out.println(Thread.currentThread().getName()+" 生产了一个 "+1+" 总共还有 "+size); //唤醒所有线程
notifyAll(); }finally {
}
} /*
* 消费者消费方法
*/
public synchronized void consum(){ try{
//如果当前大小减去要消费的值,如果小于0的话,则进入等待
while(size-1<0){
try {
wait();
System.out.println(Thread.currentThread().getName()+" 消费者进入等待状态"); } catch (Exception e) {
e.printStackTrace();
}
} size-=1;
System.out.println(Thread.currentThread().getName()+" 消费者消费了 "+1+" 个,总共还有 "+size);
//唤醒所有线程
notifyAll(); }finally {
}
}
}
运行结果:
对比:
首先可以看出两个都可以实现生产者消费者的工作,不过可以发现Condition的signal相对于Object的notify最大有点就是它可以唤醒指定的线程,
比如这里可以指定唤醒生产线程或者消费线程,而用notify是不能唤醒指定线程的,你只能通过notifyAll来唤醒所有。
想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。少校【14】
java多线程(7)---Condition的更多相关文章
- Java多线程——Lock&Condition
Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. package ...
- java 多线程 day13 condition 线程通信
/** * Created by chengtao on 17/12/5. * Condition 类似 wait和notify,解决线程间的同步问题 */ import java.util.conc ...
- 玩转Java多线程(Lock.Condition的正确使用姿势)
转载请标明博客的地址 本人博客和github账号,如果对你有帮助请在本人github项目AioSocket上点个star,激励作者对社区贡献 个人博客:https://www.cnblogs.com/ ...
- Java多线程系列--“JUC锁”06之 Condition条件
概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...
- Java多线程——Condition条件
简介 Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signa ...
- Java多线程(九)之ReentrantLock与Condition
一.ReentrantLock 类 1.1 什么是reentrantlock java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 ...
- Java多线程系列--“JUC锁”03之 公平锁(一)
概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...
- Java多线程系列--“JUC锁”04之 公平锁(二)
概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...
- Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例
概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...
- Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock
本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...
随机推荐
- *CTF 2019 quicksort、babyshell、upxofcpp
这次参加比赛总共出了三道,有两道队友都先交了,还是tcl,heap_master卡了差不多一天没解决....还是记录一下出的题目吧 quicksort 题目大体流程就是输入要输入的数字数量,然后输入数 ...
- 在命令行输入python出现“Warning:This Python interpreter is in a conda environment, but the environment has not been activated. Libraries may fail to load. To activate this environment please see https://conda.
[现象] 在命令行输入python出现“Warning:This Python interpreter is in a conda environment, but the environment h ...
- Python3-Cookbook总结 - 第三章:数字日期和时间
第三章:数字日期和时间 在Python中执行整数和浮点数的数学运算时很简单的. 尽管如此,如果你需要执行分数.数组或者是日期和时间的运算的话,就得做更多的工作了. 本章集中讨论的就是这些主题. Con ...
- 源生API解析XML文档与dom4j解析XML文档
一.XML语言 XML是一种可扩展的标记语言,是一种强类型的语言,类似HTML(超文本标记语言,是一种弱类型的语言).XML是一种通用的数据交换格式(关系型数据库),综上所诉:XML可以传输数据,也可 ...
- 2019 蓝桥杯省赛 A 组模拟赛(一)-修建公路
题目: 蒜头国有 nn 座城市,编号分别为 0,1,2,3,...,n-1.编号为 x 和 y 的两座城市之间如果要修高速公路,必须花费 x|y 个金币,其中|表示二进制按位或. 吝啬的国王想要花最少 ...
- photoshop改变图片大小,不改变像素
用画图修改了图片像素,360*440 但是图片30K,要求图片20K 打开photoshop,打开图片,点击文件--存储为web所用格式,调节品质大小到20K以下,保存即可
- 心得体会,搞清楚你为什么学习C++?
小编作为一名初学者时,从来没问过自己学习C语言.C++等语言是为了什么? 一开始,接触到这个行业可以说是有种魔力引导我,感到了很大的兴趣,很有意思. 我试着读资料,报名学习,找资料,可算是功夫不负有心 ...
- Android SQLite数据库升级,怎么做(事物更改)
SQLiteOpenHelper // 如果数据库文件不存在,只有onCreate()被调用(该方法在创建数据库时被调用一次) public abstract void onCreate(SQLite ...
- 匿名函数 javascript
匿名函数: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- 上传插件webupload之调用拍照兼容问题
在项目中,移动端用到了webupload插件来实现上传功能(我觉得这个插件挺好用的,所以无论pc还是移动端我都使用了这个插件来做上传功能) 在移动端要调起拍照功能,实现上传,须得在webuploade ...