任意一个Java对象,都拥有一组监视器方法(定义在根类Object上),主要包括:wait( )、wait(long timeout)、notify()、notifyAll()方法;这些方法与关键字synchronized结合使用,可以实现 隐式锁的等待/通知机制。而显示锁Lock也实现了等待/通知机制;Condition接口也提供了类似Object的监视器方法,与Lock配合使用可以实现 显式锁的等待/通知机制,但是两者在使用方式和功能特性有所差别。总得来说,Condition接口更加灵活,功能更多:

  • Condition 接口是支持多个等待队列,也称为条件队列,即根据不同的条件进入不同的等待队列,相应的,用户便可以只在指定的等待队列上唤醒线程,而不是唤醒所有的线程。而 Object监视器 则只能有一个等待队列。
  • Condition 接口还提供了对中断不敏感的等待方法,即当处于等待状态时,是不会被中断的。而Object监视器 不支持不可中断的等待。
  • Condition 接口除了提供了超时等待方法之外,还提供了等待直到将来某个时间段的方法;Object监视器只有超时等待的方法。

Condition 接口的方法:

方法名称 描 述
void await() throws InterruptedException 造成当前线程在接到通知或被中断之前一直处于等待状态。即发生以下两种情况,将会从await()方法返回:
1、其他某个线程调用此 Condition 的 signal()、signalAll()方法;
2、其他某个线程中断当前线程
void awaitUninterruptibly() 造成当前线程在接到通知之前一直处于等待状态。 与await()方法相比,这是不可中断的等待方法
long awaitNanos(long nanosTimeout) throws InterruptedException 造成当前线程在接到通知、被中断或到达指定等待时间之前一直处于等待状态。
返回值:此方法返回时,距离超时的剩余时间,即返回值就是(nanosTimeout - 实际耗时);如果返回值是0或者负数,那么认定已经超时
boolean await(long time, TimeUnit unit) throws InterruptedException 造成当前线程在接到通知、被中断或到达指定等待时间之前一直处于等待状态。
返回值:如果在从此方法返回前检测到等待时间超时(到达指定时间),则返回 false,否则返回 true
此方法在行为上等效于: awaitNanos(unit.toNanos(time)) > 0
boolean awaitUntil(Date deadline) throws InterruptedException 造成当前线程在接到通知、被中断或到达指定最后期限之前一直处于等待状态。
返回值:如果在从此方法返回前检测到等待时间超时(到达指定时间),则返回 false,否则返回 true
void signal() 唤醒一个等待线程。如果所有的线程都在等待此条件,则选择其中的一个唤醒。在从 await 返回之前,该线程必须重新获取锁。
void signalAll() 唤醒所有等待线程。 如果所有的线程都在等待此条件,则唤醒所有线程。在从 await 返回之前,每个线程都必须重新获取锁。

@ Example Condition 的例子

public class BoundedQueue<T> {
private Object[] item;
//添加的下标、删除的下标、数组的当前数量
private int addIndex,removeIndex,count;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition(); public BoundedQueue(int size){
item = new Object[size];
} //添加一个元素,如果数组满,则添加线程进入等待状态,直到有空位
public void add(T t) throws InterruptedException{
lock.lock();
try{
while(count == item.length){
//可中断的等待,如果没有剩余空间,那么就进入notFull的等待队列
notFull.wait();
}
item[addIndex] = t;
if(++addIndex == item.length){//模拟环数组,一直插入,直到尾部,又重新从头部插入
addIndex = 0;
}
count++;
//刚插入一个元素,不为空的条件满足,可唤醒等待在notEmpty队列上的线程
notEmpty.signal();
}finally {
lock.unlock();
}
} //从头部移除一个元素,如果数组为空,则等待,直到数组不为空
public T remove(){
lock.lock();
try{
while(count == 0){
//不可中断的等待,不为空的条件不满足,就会一直等待
notEmpty.awaitUninterruptibly();;
}
Object x = item[removeIndex];
if(++removeIndex == item.length){
removeIndex = 0;
}
count--;
//刚移除一个元素,数组没有满的条件符合,唤醒等待在notFull上的线程
notFull.signal();
return (T)x;
}finally{
lock.unlock();
}
}
}

显式锁(四)Lock的等待通知机制Condition的更多相关文章

  1. 【java并发编程】十三章:显式锁:LOCK

    java5以后,新增了显式锁,用于当内置锁不能满足需求后可选择的一种高级方案. lock接口的特点 与内置锁一样,他能提供互斥性,内存可见性,可重入等特征,与内置锁不同的是,Lock提供了一种无条件, ...

  2. ReentrantLock等待通知机制Condition介绍

    Object类中的wait(),notify()和notifyAll()可以实现线程的等待通知模型,同样在ReentrantLock中可以借助Condition来完成这种机制.本篇就简要介绍Condi ...

  3. Java并发之显式锁和隐式锁的区别

    Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchr ...

  4. Java编程的逻辑 (71) - 显式锁

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  5. “全栈2019”Java多线程第三十二章:显式锁Lock等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  6. 显式锁(二)Lock接口与显示锁介绍

    一.显式锁简介    显式锁,这个叫法是相对于隐式锁synchronized而言的,加锁和解锁都要用户显式地控制.显示锁Lock是在Java5中添加到jdk的,同synchronized一样,这也是一 ...

  7. java并发多线程显式锁Condition条件简介分析与监视器 多线程下篇(四)

    Lock接口提供了方法Condition newCondition();用于获取对应锁的条件,可以在这个条件对象上调用监视器方法 可以理解为,原本借助于synchronized关键字以及锁对象,配备了 ...

  8. java里的锁总结(synchronized隐式锁、Lock显式锁、volatile、CAS)

    一.介绍 首先, java 的锁分为两类: 第一类是 synchronized 同步关键字,这个关键字属于隐式的锁,是 jvm 层面实现,使用的时候看不见: 第二类是在 jdk5 后增加的 Lock ...

  9. “全栈2019”Java多线程第三十一章:中断正在等待显式锁的线程

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. preprocessor设置调试宏

    调试宏:preprocessor设置 预处理器“调试”宏在Xcode项目模板的调试版本定义.预处理宏在编译时被解释和调试宏可以用来允许调试代码运行在调试版本中你的项目.如果你不确定你的项目已经确定,可 ...

  2. python3获取当前目录和上级目录

    d = path.dirname(__file__) #返回当前文件所在的目录 # __file__ 为当前文件 获得某个路径的父级目录: parent_path = os.path.dirname( ...

  3. POJ3276(遍历+区间修改)

    http://poj.org/problem?id=3276 题意:n(n<=5000)头牛站成线,有朝前有朝后的的,然后每次可以选择大小为k的区间里的牛全部转向,会有一个最小操作m次使得它们全 ...

  4. 《DSP using MATLAB》Problem 4.13

    代码: %% ---------------------------------------------------------------------------- %% Output Info a ...

  5. BC32(hdu5182~5185)

    恩……又是一个悲伤的故事,然后BC做出来一题,因为自己傻逼,可能紧张,也可能是其他,反正没看全题目就敲,敲完WA,WA完改,改完WA,没了……大概五十几分钟WA了五法,然后问了才知道没看全,就这样,后 ...

  6. 横竖两个数字塔的效果BAT批处理怎么写?

    横竖两个数字塔的效果BAT批处理怎么写?@echo offfor /l %%a in (0,1,1) do (        for /l %%i in (0,1,9) do (        for ...

  7. 用 c 写 CGI 程序简要指南

    文章摘要:  CGI规定了Web服务器调用其他可执行程序(CGI程 序)的接口协议标准.Web服务器通过调用CGI程序实现和Web浏览器的交互.CGI程序可以用任何程序设计语言编写,如Shell脚本语 ...

  8. tomcat catalina.out切割脚本

    shell脚本catalina.out 切割脚本...每天23.30切割.删除七天之前的日志这里3个tomcat实例(1)拷贝日志文件(2)清空日志文件*只能清空如果删除tomcat不重启不会生成新的 ...

  9. selenium启动谷歌所遇到的问题

    最近在学习selenium webdriver,发现启动火狐时,运行非常慢,几天前一直在尝试启动谷歌驱动启动,但启动中总遇到问题,启动不起来,一直百度查找方法,还是没搞定,个人比较执着,爱钻牛角尖,弄 ...

  10. 我的主机是win 7 虚拟机是vmware,solaris10连接主机

    进入主机Control Panel—Administrative Tool—Services,打开服务Vmware DHCP Servise和Vmware NAT Service,启动后虚拟机上网正常 ...