java.util.concurrent.locks.Condition文档说明

【1】Condition接口文档描述

1.Condition类把Object监视器方法(wait,nofify, notifyAll)分解为不同对象,通过与Lock实现类的合并使用,Condition可以产生每个object都有多个等待集的效果在Lock实现类替代synchronized方法或语句块的地方,Condition可以替换Object监视器方法

2.Conditions(也称为条件队列或条件变量),为一个线程提供了挂起执行(等待)的方法,直到另一个线程通知它某些状态条件可能为真。

3.因为对共享状态信息的访问发生在不同线程,该共享信息必须被保护,因此某种形式的锁与condition条件相关联。等待条件提供的关键属性是它(条件-condition)可以原子性释放关联的锁并挂起当前线程,就像Object.wait() 方法那样。

4.condition-条件实例本质上是绑定到锁Lock上的。要获取特定Lock实例的条件对象,使用newCondition() 方法;

5.举个例子(这个例子非常经典-类似消息队列),假设我们有一个支持put和take 方法的有界缓冲区。若尝试对空缓存区执行take操作,则线程阻塞直到缓冲区有元素;若尝试对满缓存区执行put操作,则线程阻塞直到缓存区有可用空间。 我们想要把 执行put方法和task方法阻塞的线程放在单独的等待集合中,以便我们可以使用优化,当缓存区中元素或空间可用时, 仅通知一个线程。

这可以通过使用两个 Condition-条件实例来实现,如下(这段代码非常重要):

class BoundedBuffer { // 有界缓冲区 final Lock lock = new ReentrantLock();// 可重入锁final Condition notFull  = lock.newCondition(); // 不为满的条件final Condition notEmpty = lock.newCondition(); // 不为空的条件final Object[] items = new Object[100];int putptr, takeptr, count;// 插入元素 public void put(Object x) throws InterruptedException {lock.lock();// 获取锁 try {while (count == items.length)// 当缓冲区满,则自旋式阻塞notFull.await();// 等待 items[putptr] = x;// 不满,则添加元素到缓冲区 if (++putptr == items.length) putptr = 0;++count;notEmpty.signal();// 唤醒在非空条件上阻塞的线程} finally {lock.unlock();// 解锁}}// 获取元素 public Object take() throws InterruptedException {lock.lock();// 获取锁 try {while (count == 0)notEmpty.await();// 若缓存区空,则非空条件阻塞 Object x = items[takeptr];if (++takeptr == items.length) takeptr = 0;--count;notFull.signal();// 唤醒非满条件return x;} finally {lock.unlock();// 解锁}}}

java.util.concurrent.ArrayBlockingQueue实现了上述例子,无需自己写代码实现)

6.Condition实现类可以提供不同于Object监视器方法的行为和语义,如保证通知顺序,执行通知时无需持有锁。如果一个Condition实现类提供了这些专门语义,则需要记录这些语义。

7.注意到:

  • Condition实例也仅仅是普通对象,所以可以作为 synchronized方法或语句块的目标对象,也可以调用Condition对象的监视器wait() 和 notify方法。获取Condition实例的监视器锁,或使用监视器方法(wait,notify,notifyAll),与获取condition相关的Lock锁或使用其wait或signal方法没有任何关系。墙裂建议为了避免混淆,不要在把 Conditoin实例作为 synchronized的目标对象,除非在它们自己的实现中。

8.Condition实现类注意事项:

在等待条件时,通常允许发生虚假唤醒,作为对底层平台语义的让步。

这对大多数应用程序来说没有影响,因为condition-条件应该始终在循环中等待,以测试等待的状态谓词(变量是否为真)

Conditon实现类可以自由移除虚假唤醒的可能性,但墙裂建议程序员始终假设它可能发生,因此始终在循环中等待

9.3种形式的条件等待(可中断,不可中断,超时)在一些平台的实现难易程度和性能特征有所不同。特别地,可能很难提供这些特性并维护特定语义,如顺序保证。此外,中断一个线程的实际挂起的能力在所有平台并不总是可行的;

10.因此,Condition实现类不需要为以上3种形式的等待精确定义同样的保证和语义。也不需要支持对线程实际挂起的中断。

11.一个Condition实现类需要记录每个wait方法提供的语义和保证,当Condition实现类支持线程挂起时的中断,则它必须遵守本接口定义的中断语义。

12.中断通常意味着取消,并且中断检测不常发生,所以Condition实现类倾向于响应中断而不是方法正常返回。即使证明中断发生在另一动作解除线程阻塞之后发生,也是如此。Condition实现类应该记录这些行为。


【2】Condition方法

【2.1】void await() throws InterruptedException

1.该方法导致当前线程等待,直到收到信号或被中断

2.与此Condition关联的锁被自动释放,且当前线程无法被线程调度器调度(禁用),并处于休眠状态直到以下4种情况之一发生:

  • 情况1,其他线程调用此condition的信号方法(signal),并且当前线程恰好被选择为要被唤醒的线程 ;
  • 情况2 ,其他线程调用此condition的signalAll方法;
  • 情况3 , 其他线程中断了当前线程,(当Condition实现类支持线程挂起时的中断);
  • 情况4, 发生虚假唤醒(?)

3.在所有情况下,在await() 方法从当前线程返回之前,当前线程都必须重新获取与condition关联的锁。当线程返回时,能够保证它持有锁。

4.如果当前线程:

在该方法入口设置了中断状态,或等待时被中断(且condition实现类支持线程挂起时被中断),

则线程将抛出InterruptedException-中断异常,且当前线程的中断状态被清空。

对于第一种情况,在释放锁之前是否进行中断测试没有规定。

5.Condition实现类注意事项:

在本方法被调用时,假设当前线程持有了condition对象关联的锁。

这取决于condition实现类确定是否是这种情况,如果不是,如何响应。通常,会抛出异常(如IllegalMonitorStateException-非法监视器状态异常),且condition实现类会记录该事实。

6.在响应信号过程中,condition实现类倾向于响应中断而不是方法正常返回。在那种情况下,condition实现类必须保证信号被重定向到其他等待线程(即,sinal发给其他线程以唤醒),如果有的话 。

7.抛出异常:

InterruptedException-中断异常,当当前线程被中断(当condition实现类支持线程挂起时中断)


【2.2】void awaitUninterruptibly()

1.导致当前线程等待,直到被发出信号

2.与此contition对象关联的锁被自动释放,当前线程无法被线程调度器调度(禁用), 并休眠直到以下3种情况之一发生

  • 情况1, 其他线程调用了该condition对象的 signal() 方法,且当前线程被选为要唤醒的线程;
  • 情况2,其他线程调用了 该condition对象的 signalAll() 方法;
  • 情况3,发生 虚假唤醒(?);

3.在所有情况下,在awaitUninterruptibly() 方法从当前线程返回之前,当前线程都必须重新获取与condition关联的锁。当线程返回时,能够保证它持有锁。

4.若在该方法入口设置了当前线程的中断状态,或等待时被中断(且condition实现类支持线程挂起时被中断),该线程会继续等待直到接收到信号(不会中断)。当线程最终从该方法返回时,它的中断状态仍然被设置。

5.Condition实现类注意事项:

在本方法被调用时,假设当前线程持有了condition对象关联的锁。

这取决于condition实现类确定是否是这种情况,如果不是,如何响应。通常,会抛出异常(如IllegalMonitorStateException-非法监视器状态异常),且condition实现类会记录该事实。


【2.3】long awaitNanos(long nanosTimeout) throws InterruptedException

1.导致当前线程等待直到接收到信号,或被中断,或经过给定的等待时间。

2.与此contition对象关联的锁被自动释放,当前线程无法被线程调度器调度(禁用), 并休眠直到以下5种情况之一发生

  • 情况1, 其他线程调用了该condition对象的 signal() 方法,且当前线程被选为要唤醒的线程;
  • 情况2,其他线程调用了 该condition对象的 signalAll() 方法;
  • 情况3,其他线程中断了当前线程,(当Condition实现类支持线程挂起时的中断);
  • 情况4,经过给定的等待时间;
  • 情况5,虚假唤醒;

3.在所有情况下,在该方法从当前线程返回之前,当前线程都必须重新获取与condition关联的锁。当线程返回时,能够保证它持有锁。

4.若在该方法入口设置了当前线程的中断状态,或等待时被中断(且condition实现类支持线程挂起时被中断),则线程将抛出InterruptedException-中断异常,且当前线程的中断状态被清空。

对于第一种情况,在释放锁之前是否进行中断测试没有规定。

5.该方法根据给定的超时纳秒数返回剩余等待纳秒数的估计值。若超时,则该值小于或等于0.

该值可以用于确定在等待返回但等待条件不满足的情况下是否重新等待以及重新等待多长时间。典型用法如下:

 boolean aMethod(long timeout, TimeUnit unit) {long nanos = unit.toNanos(timeout);lock.lock();try {while (!conditionBeingWaitedFor()) {if (nanos <= 0L)return false;nanos = theCondition.awaitNanos(nanos);}// ...} finally {lock.unlock();}}

设计说明:该方法需要一个纳秒参数,以避免报告剩余时间时出现截断错误。这样的精度丢失将使程序员难以确保系统上的总等待时间不会短于重新等待时的指定值。

6.condition实现类注意事项:

在本方法被调用时,假设当前线程持有了condition对象关联的锁。

这取决于condition实现类确定是否是这种情况,如果不是,如何响应。通常,会抛出异常(如IllegalMonitorStateException-非法监视器状态异常),且condition实现类会记录该事实。

7.在响应信号过程中,condition实现类倾向于响应中断而不是方法正常返回或者超过给定等待时间。在任何情况下,condition实现类必须保证信号被重定向到其他等待线程(即,sinal发给其他线程以唤醒),如果有的话 。

8.参数:

  • nanosTimeout, 最大等待时间的纳秒数;

9.返回:

  • 给定的最大等待时间减去等待花费时间的估计值。正数可以用于该方法的后续调用以完成等待所需时间。该值小于或等于0,表明没有剩余的等待时间了,即无需再等待了。

10.抛出异常

  • InterruptedException-中断异常,如果当前线程被中断(condition实现类支持线程挂起时中断)

【2.4】boolean await(long time, TimeUnit unit) throws InterruptedException

1.导致当前线程等待直到接收到信号,或被中断,或经过给定的等待时间。该方法等价于 awaitNanos(...) 方法

  awaitNanos(unit.toNanos(time)) > 0

2.参数

  • time, 等待的最长时间;
  • unit,time参数的单位,如时、分、秒

3.返回:

  • 若方法返回前可以检测到等待时间已经过去,则返回false;否则返回true;
  • 即等待已超时,返回false,否则返回true;

4.抛出异常:

  • InterruptedException-中断异常,如果当前线程被中断(condition实现类支持线程挂起时中断)

【2.5】boolean awaitUntil(Date deadline) throws InterruptedException

1.导致当前线程等待直到收到信号,或中断,或经过了给定的截止日期。

2.与condition关联的锁会被自动释放,且当前线程会被线程调度器禁用并休眠,直到以下5种情况之一发生:

  • 情况1,其他线程调用signal() 信号方法,且当前线程被选为要唤醒的线程;
  • 情况2,其他线程调用 signalAll()方法;
  • 情况3,其他线程中断了当前线程(condition实现类支持线程挂起时中断);
  • 情况4,经过指定的截止日期;
  • 情况5,发生虚假唤醒;

3.在所有情况下,在该方法从当前线程返回之前,当前线程都必须重新获取与condition关联的锁。当线程返回时,能够保证它持有锁。

4.若在该方法入口设置了当前线程的中断状态,或等待时被中断(且condition实现类支持线程挂起时被中断),则线程将抛出InterruptedException-中断异常,且当前线程的中断状态被清空。

对于第一种情况,在释放锁之前是否进行中断测试没有规定。

5.返回值 表明是否经过了截止期限,可以如下使用:

 boolean aMethod(Date deadline) {boolean stillWaiting = true;lock.lock();try {while (!conditionBeingWaitedFor()) {if (!stillWaiting)return false;stillWaiting = theCondition.awaitUntil(deadline);// 等待,返回是否过了截止期限}// ...} finally {lock.unlock();}}

6.实施注意事项

在本方法被调用时,假设当前线程持有了condition对象关联的锁。

这取决于condition实现类确定是否是这种情况,如果不是,如何响应。通常,会抛出异常(如IllegalMonitorStateException-非法监视器状态异常),且condition实现类会记录该事实。

7.在响应信号过程中,condition实现类倾向于响应中断而不是方法正常返回或者超过给定截止时间。在任何情况下,condition实现类必须保证信号被重定向到其他等待线程(即,sinal发给其他线程以唤醒),如果有的话 。

8.参数

  • deadline, 等待的绝对时间;

9.返回

  • 如果经过了等待时间返回false, 否则true;

10.抛出异常:

  • InterruptedException-中断异常,如果当前线程被中断(condition实现类支持线程挂起时中断)

【2.6】void signal()

1.唤醒一个等待线程

2.如果有多个线程在等待condition-条件,则其中一个线程将被选中进行唤醒。那个选中的线程在从await()方法返回之前,必须重新获取锁;

3.实施注意事项

该方法被调用时, condition实现类可能要求(通常要求)当前线程需要持有与condition对象关联的锁;condition实现类必须记录这个先决条件以及在未持有锁的情况下采取的任何动作;通常,会抛出异常,如IllegalMonitorStateException;


【2.7】void signalAll()

1.唤醒所有等待线程;

2.如果有线程在等待该条件,则所有等待线程都会被唤醒; 每个线程在从 await() 方法返回之前必须重新获取锁;

3.condition实现类注意事项

该方法被调用时, condition实现类可能要求(通常要求)当前线程需要持有与condition对象关联的锁;condition实现类必须记录这个先决条件以及在未持有锁的情况下采取的任何动作;通常,会抛出异常,如IllegalMonitorStateException;


【3】方法总结

【3.2】等待方法

condition等待方法列表
方法名描述
void await() throws InterruptedException

该方法导致当前线程等待,直到收到信号或被中断。

出现以下4种情况之一,线程恢复可运行状态:

情况1,其他调用condition.signal(),且该线程被选中作为要唤醒的线程;

情况2,其他线程调用 condition.signalAll(), 唤醒所有等待线程;

情况3,发生中断;

情况4,发送虚假唤醒;

void awaitUninterruptibly();

该方法导致当前线程等待,直到收到信号;

出现以下3种情况之一,线程恢复可运行状态:

情况1,其他调用condition.signal(),且该线程被选中作为要唤醒的线程;

情况2,其他线程调用 condition.signalAll(), 唤醒所有等待线程;

情况3,发送虚假唤醒;

long awaitNanos(long nanosTimeout) throws InterruptedException;

该方法导致当前线程等待,直到收到信号或被中断或经过给定等待时间。

出现以5种情况之一,线程恢复可运行状态:

情况1,其他调用condition.signal(),且该线程被选中作为要唤醒的线程;

情况2,其他线程调用 condition.signalAll(), 唤醒所有等待线程;

情况3,发生中断;

情况4,经过给定的等待时间;

情况5,发送虚假唤醒;

boolean await(long time, TimeUnit unit) throws InterruptedException;导致当前线程等待直到接收到信号,或被中断,或经过给定的等待时间。该方法等价于 awaitNanos(...) 方法
boolean awaitUntil(Date deadline) throws InterruptedException;

导致当前线程等待直到收到信号,或中断,或经过了给定的截止日期。

出现以5种情况之一,线程恢复可运行状态:

情况1,其他调用condition.signal(),且该线程被选中作为要唤醒的线程;

情况2,其他线程调用 condition.signalAll(), 唤醒所有等待线程;

情况3,发生中断;

情况4,经过指定的截止日期;

情况5,发送虚假唤醒;

【3.2】唤醒方法

condition唤醒方法列表
方法名描述
void signal()

唤醒一个等待线程

如果有多个线程在等待condition-条件,则其中一个线程将被选中进行唤醒。那个选中的线程在从await()方法返回之前,必须重新获取锁;

void signalAll()

唤醒所有等待线程

如果有线程在等待该条件,则所有等待线程都会被唤醒; 每个线程在从 await() 方法返回之前必须重新获取锁;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谈谈HashMap线程不安全的体现

转载自 谈谈HashMap线程不安全的体现HashMap的原理以及如何实现&#xff0c;之前在JDK7与JDK8中HashMap的实现中已经说明了。那么&#xff0c;为什么说HashMap是线程不安全的呢&#xff1f;它在多线程环境下&#xff0c;会发生什么情况呢&#xff1f;1. resize死循环我们都知道…

手机打开python文件_使用python在计算机和手机之间通过wifi进行简单的文件传输...

我会使用 paramiko.它安全快速而且非常简单.怎么回事&#xff1f; 所以我们首先导入模块,然后指定日志文件&#xff1a; import paramiko paramiko.util.log_to_file(/tmp/paramiko.log) 我们打开一个SSH传输&#xff1a; host "example.com" port 22 transport p…

10人以下小团队管理手册-学习笔记

【README】 本文总结于《10人以下小团队管理手册》&#xff0c;很nice的一本书&#xff0c;有兴趣的同学可以翻下&#xff1b; 【0】序章 作者作为咨询师发现&#xff0c; 1.下属对主管有不满&#xff0c;主管对下属有怨言&#xff1b; 2.10人以下小团队主管经常会为 如何用…

JavaWeb项目:简易小米商城系统

Web项目&#xff1a;MyShop简易小米商城系统一.系统概述二.系统开发环境三.涉及技术四.系统功能及使用说明五.作者杂谈六.尾声七.gitee地址&#xff1a;&#xff08;源码见文末&#xff09; 一.系统概述 本系统是一个电商系统&#xff0c;可供用户注册&#xff0c;登录&#…

HashMap的实现与优化

转载自 HashMap的实现与优化HashMap的优化与实践 本文是基于作者在github上的Android 问题交流讨论坛提问而产生的一篇文章&#xff0c;也是自己早打算开坑的一篇文章。文章首先介绍了hashMap的一些基本知识&#xff0c;然后介绍了它在JDK8下的实现原理&#xff0c;最后着重介绍…

如何确定python开发环境已经配置好_搭建 python 开发环境 前面安装选位置我直接回车了现在我想测试查看目录该怎么办...

展开全部 1 ubuntu中一般安装e5a48de588b662616964757a686964616f31333431343036后的默认路径如下#!/usr/bin/env python #!/usr/locat/bin/python 如果没有找到&#xff0c;可以通过命令查询python路径whereis python which python 2 Windows一般可以进入python>>> i…

转- java单例模式几种实现方式

转自&#xff1a; https://www.cnblogs.com/ngy0217/p/9006716.html &#xff1b; 单例模式的五种实现方式 1、饿汉式(线程安全&#xff0c;调用效率高&#xff0c;但是不能延时加载)&#xff1a; 1 2 3 4 5 6 7 public class ImageLoader{ private static ImageLoade…

IDEA集成maven流程图详细介绍

前言 最近利用两天时间学习了MyBatis以及maven,避免经典的学过就忘记&#xff0c;我打算做出点总结以便日后复习&#xff0c;当然如果能帮到需要的人也是极好的。 一. 初识maven 1.maven是什么 maven是用来帮助我们快速搭建项目结构与开发环境的好工具。回想一下每次新建项…

pythonnumpy教程_Python教程:numpy的基本介绍

标准安装的Python中用列表(list)保存一组值&#xff0c;可以用来当作数组使用&#xff0c;不过由于列表的元素可以是任何对象&#xff0c;因此列表中所保存的是对象的指针。这样为了保存一个简单的[1,2,3]&#xff0c;需要有3个指针和三个整数对象。对于数值运算来说这种结构显…

Java8系列之重新认识HashMap

转载自 Java8系列之重新认识HashMap简介 Java为数据结构中的映射定义了一个接口java.util.Map&#xff0c;此接口主要有四个常用的实现类&#xff0c;分别是HashMap、Hashtable、LinkedHashMap和TreeMap&#xff0c;类继承关系如下图所示&#xff1a;下面针对各个实现类的特点做…

mysql-on duplicate key update实现insertOrUpdate官方文档

【README】 mysql 基于 on duplicate key update filedvalue ; 实现有则更新&#xff0c;没有则插入&#xff1b; 以下内容总结于 https://dev.mysql.com/doc/refman/8.0/en/insert-on-duplicate.html 【1】api 描述 如果指定 ON DUPLICATE KEY UPDATE 子句并且要插入的行…

python统计段落单词词频_使用Python统计文件中词频,并且生成词云

wordcloud Table of Contents 1 怎样使用Python产生词云 from wordcloud import WordCloud import matplotlib.pyplot as plt import jieba # Now, There is no word.txt under this path path_txt "/home/alan/Desktop/word.txt" f open(path_txt, r, encoding U…

IDEA中maven配置MyBatis简单流程

前言 刚学完javaweb&#xff0c;对自己的Dao层代码很不满意的话&#xff0c;可得来学学MyBatis。学习MyBatis既可以改进JDBC的使用&#xff0c;实现Dao层也会变得很简便&#xff0c;下面我将介绍IDEA中maven配置MyBatis简单流程。 如果想了解maven请转到我的上一篇文章中&…

(转)构建微服务:Spring boot 入门篇

转自&#xff1a; Spring Boot(一)&#xff1a;入门篇 - 纯洁的微笑 - 博客园 &#xff1b; 什么是Spring Boot Spring Boot 是由 Pivotal 团队提供的全新框架&#xff0c;其设计目的是用来简化新 Spring 应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置&#…

python参数_python参数的介绍

一、函数 1.为什么要使用函数&#xff1f; 减少代码的冗余 2.函数先定义后使用&#xff08;相当于变量一样先定义后使用&#xff09; 3.函数的分类&#xff1a; 内置函数&#xff1a;python解释器自带的&#xff0c;直接拿来用就行了 自定义函数&#xff1a;根据自己的需求自己…

一篇文章指明做JavaWeb项目需要的前置知识+完整项目初解读(萌新必看,十分友好)

前言 过了web这个阶段了&#xff0c;项目也完成了的我想给各位后来者总结一下我整个项目从开始到结束的经验&#xff0c;当然&#xff0c;也不是一帆风顺&#xff0c;报错有时候折磨的要死&#xff0c;废话不多说&#xff0c;现在就开始吧。 本文一共分为两个部分&#xff1a;…

HashMap 实现原理

转载自 HashMap 实现原理HashMap是常考点&#xff0c;而一般不问List的几个实现类(偏简单)。以下基于JDK1.8.0_102分析。 内部存储 HashMap的内部存储是一个数组&#xff08;bucket&#xff09;&#xff0c;数组的元素Node实现了是Map.Entry接口(hash, key, value, next)&#…

mybatis-启动源码分析

【1】测试用例 mybatis-config.xml <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configurat…

git 合并冲突_git分支管理的策略和冲突问题

备注&#xff1a;知识点关于分支中的冲突分支管理的策略分支策略备注&#xff1a;本文参考于廖雪峰老师的博客Git教程。依照其博客进行学习和记录&#xff0c;感谢其无私分享&#xff0c;也欢迎各位查看原文。知识点git log --graph --prettyoneline --abbrev-commit查看分支合…

mysql duplicate key与replace into对比

【REDME】 有些业务场景如下&#xff1a; 对于数据已经存在的&#xff0c;则更新&#xff1b;否则新增&#xff1b; 怎么判定数据已经存在&#xff0c;通过主键或唯一索引来判断&#xff1b; 业务场景&#xff1a;业务库的全局参数表的参数值的新增或更新就是 有则更细无则…