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的更多相关文章

  1. Java多线程——Lock&Condition

    Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互斥的效果,它们必须用同一个Lock对象. package ...

  2. java 多线程 day13 condition 线程通信

    /** * Created by chengtao on 17/12/5. * Condition 类似 wait和notify,解决线程间的同步问题 */ import java.util.conc ...

  3. 玩转Java多线程(Lock.Condition的正确使用姿势)

    转载请标明博客的地址 本人博客和github账号,如果对你有帮助请在本人github项目AioSocket上点个star,激励作者对社区贡献 个人博客:https://www.cnblogs.com/ ...

  4. Java多线程系列--“JUC锁”06之 Condition条件

    概要 前面对JUC包中的锁的原理进行了介绍,本章会JUC中对与锁经常配合使用的Condition进行介绍,内容包括:Condition介绍Condition函数列表Condition示例转载请注明出处 ...

  5. Java多线程——Condition条件

    简介 Condition中的await()方法相当于Object的wait()方法,Condition中的signal()方法相当于Object的notify()方法,Condition中的signa ...

  6. Java多线程(九)之ReentrantLock与Condition

    一.ReentrantLock 类   1.1 什么是reentrantlock   java.util.concurrent.lock 中的 Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 ...

  7. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  8. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  9. Java多线程系列--“JUC锁”10之 CyclicBarrier原理和示例

    概要 本章介绍JUC包中的CyclicBarrier锁.内容包括:CyclicBarrier简介CyclicBarrier数据结构CyclicBarrier源码分析(基于JDK1.7.0_40)Cyc ...

  10. Java多线程系列--“JUC锁”02之 互斥锁ReentrantLock

    本章对ReentrantLock包进行基本介绍,这一章主要对ReentrantLock进行概括性的介绍,内容包括:ReentrantLock介绍ReentrantLock函数列表ReentrantLo ...

随机推荐

  1. *CTF 2019 quicksort、babyshell、upxofcpp

    这次参加比赛总共出了三道,有两道队友都先交了,还是tcl,heap_master卡了差不多一天没解决....还是记录一下出的题目吧 quicksort 题目大体流程就是输入要输入的数字数量,然后输入数 ...

  2. 在命令行输入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 ...

  3. Python3-Cookbook总结 - 第三章:数字日期和时间

    第三章:数字日期和时间 在Python中执行整数和浮点数的数学运算时很简单的. 尽管如此,如果你需要执行分数.数组或者是日期和时间的运算的话,就得做更多的工作了. 本章集中讨论的就是这些主题. Con ...

  4. 源生API解析XML文档与dom4j解析XML文档

    一.XML语言 XML是一种可扩展的标记语言,是一种强类型的语言,类似HTML(超文本标记语言,是一种弱类型的语言).XML是一种通用的数据交换格式(关系型数据库),综上所诉:XML可以传输数据,也可 ...

  5. 2019 蓝桥杯省赛 A 组模拟赛(一)-修建公路

    题目: 蒜头国有 nn 座城市,编号分别为 0,1,2,3,...,n-1.编号为 x 和 y 的两座城市之间如果要修高速公路,必须花费 x|y 个金币,其中|表示二进制按位或. 吝啬的国王想要花最少 ...

  6. photoshop改变图片大小,不改变像素

    用画图修改了图片像素,360*440 但是图片30K,要求图片20K 打开photoshop,打开图片,点击文件--存储为web所用格式,调节品质大小到20K以下,保存即可

  7. 心得体会,搞清楚你为什么学习C++?

    小编作为一名初学者时,从来没问过自己学习C语言.C++等语言是为了什么? 一开始,接触到这个行业可以说是有种魔力引导我,感到了很大的兴趣,很有意思. 我试着读资料,报名学习,找资料,可算是功夫不负有心 ...

  8. Android SQLite数据库升级,怎么做(事物更改)

    SQLiteOpenHelper // 如果数据库文件不存在,只有onCreate()被调用(该方法在创建数据库时被调用一次) public abstract void onCreate(SQLite ...

  9. 匿名函数 javascript

    匿名函数: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...

  10. 上传插件webupload之调用拍照兼容问题

    在项目中,移动端用到了webupload插件来实现上传功能(我觉得这个插件挺好用的,所以无论pc还是移动端我都使用了这个插件来做上传功能) 在移动端要调起拍照功能,实现上传,须得在webuploade ...