jdk-Condition翻译

类说明

  1. Condition将Object监视器方法(wait、notify和notifyAll)分解成独立的对象,通过与任意Lock实现结合使用,从而达到每个对象拥有多个等待集(wait-sets per object)的效果。当Lock替换synchronized方法和语句的使用时,Condition则替换了Object监视器方法的使用。
  2. Conditions (也称为“条件队列(condition queues)”或“条件变量(condition variables)”)提供了一种机制,使得一个线程可以暂停执行(即“等待”),直到另一个线程通知某些状态条件现在可能为真。因为对这种共享状态信息的访问发生在不同的线程中,所以必须对其进行保护,因此某种形式的锁会与条件相关联。等待条件的关键特性是它能够原子性地(atomically)释放关联的锁并挂起当前线程,这类似于Object.wait。
  3. Condition实例本质上是与一个锁绑定的。要为特定的Lock实例获取一个Condition实例,请使用该Lock实例的newCondition()方法. 做为一个例子,假设我们有一个支持put和take方法的有界缓冲区。如果在一个空缓冲区上尝试take操作,那么线程将会阻塞,直到有可用的项目;如果在一个满缓冲区上尝试put操作,那么线程将会阻塞,直到有可用的空间。我们希望将等待的put线程和take线程放在不同的等待集(wait-sets)中,这样就可以在缓冲区中有项目或空间可用时,只通知一个线程,从而实现优化。这可以通过使用两个Condition实例来实现,代码如下:

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class BoundedBuffer<E> {

    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(E 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 E take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0) {
                notEmpty.await();
            }
            E x = (E) items[takeptr];
            if (++takeptr == items.length) {
                takeptr = 0;
            }
            --count;
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }
}

( java.util.concurrent.ArrayBlockingQueue类提供了当前函数的功能,没有理由再去实现这个样例类)
4. Condition 接口的实现可以提供与 Object 监视器方法不同的行为和语义,例如保证通知的顺序,或者在执行通知时不需要持有锁。如果某个实现提供了这种特殊化的语义,那么该实现必须对这些语义进行文档说明。
5. 请注意,Condition 实例只是普通的对象,它们可以作为 synchronized 语句的目标,并且可以调用它们自己的监视器方法,如 Object#wait 和 Object#notify。获取 Condition 实例的监视器锁或使用其监视器方法,与获取与该 Condition 关联的 Lock 或使用其 await 和 signal 方法之间没有指定的关系。为了避免混淆,建议你永远不要以这种方式使用 Condition 实例,除非可能是在它们自己的实现中。
6. 除非另有说明,对任何参数传递null值都将导致抛出 NullPointerException

实现考虑(Implementation Considerations)

  1. 当等待在一个Condition时,允许发生所谓的“虚假唤醒(“spurious wakeup” )”,这通常是由于底层平台语义所做出的妥协。这对大多数应用程序来说几乎没有实际影响,因为等待Condition时总是应该在一个循环中进行,并测试正在等待的状态谓词。实现可以自由地消除虚假唤醒的可能性,但建议应用程序员始终假设它们可能会发生,并因此总是在循环中等待。
  2. 条件等待(condition waiting)的三种形式(可中断、不可中断和定时)在某些平台上可能在实现的难易程度和性能特征上有所不同。特别是,提供这些功能并保持特定的语义(如顺序保证)可能是困难的。此外,在所有平台上实现对线程实际挂起的中断可能并不总是可行的。
  3. 因此,实现不要求为所有三种等待形式定义完全相同的保证或语义,也不要求支持线程挂起的实际中断。 实现必须清楚地记录每种等待方法提供的语义和保证。如果某个实现确实支持线程挂起的中断,则它必须遵守此接口中定义的中断语义。
  4. 实现必须清楚地记录每种等待方法提供的语义和保证。如果某个实现确实支持线程挂起的中断,则它必须遵守此接口中定义的中断语义。
  5. 由于中断通常意味着取消,并且检查中断的情况通常很少见,实现可以选择优先响应中断而不是正常的方法返回。即使可以证明中断发生在另一个可能已经解除线程阻塞的动作之后也是如此。实现应该记录这种行为。

public interface Condition {

    /**
     * 造成线程等待,直到signalled 或者interrupted 
     * 
     * 与这个条件关联的锁会被原子性地释放,并且当前线程会变得不可调度,进入休眠状态,直到以下四种情况之一发生:
     * 1. 其他某个线程对这个Condition调用了signal方法,并且当前线程恰好被选中为要唤醒的线程
     * 2. 其他某个线程对这个Condition调用了signalAll方法
     * 3. 其他某个线程中断了当前线程,并且支持在挂起期间中断线程
     * 4. 发生了虚假唤醒。
     * 在所有情况下,这个方法返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,保证它持有这把锁
     *
     * 如果当前线程:
     * 1. 有自己的interrupted 状态设置进入这个方法
     * 2. 是interrupted在等待的时候,并且支持在挂起期间中断线程
     * 那么:
     * 抛出InterruptedException,当前线程的interrupted 状态被清除
     * 如果没有特别说明,在第一种情况下,并未指定中断检测是在释放锁之前还是之后进行
     *
     * 实现考虑:
     * 1. 当调用这个方法时,假设当前线程持有与此Condition关联的锁。由实现者来决定这种情况是否成立,
     * 如果不成立,应该如何响应。
     * 通常情况下,会抛出一个异常(例如IllegalMonitorStateException),并且实现者必须在文档中说明这一点。
     *
     * 2. 实现可以选择优先响应中断,而不是正常的方法返回(响应信号)或指示指定的截止时间已过。
     * 无论哪种情况,实现都必须确保信号被重定向到另一个等待的线程(如果有其他等待的线程)。
     *
     * @throws 如果当前线程被中断(并且支持中断线程挂起),则抛出InterruptedException。
     */
    void await() throws InterruptedException;

    /**
     * 造成线程等待,直到signalled
     * 与这个条件关联的锁会被原子性地释放,并且当前线程会变得不可调度,进入休眠状态,直到以下四种情况之一发生:
     * 1. 其他某个线程对这个Condition调用了signal方法,并且当前线程恰好被选中为要唤醒的线程
     * 2. 其他某个线程对这个Condition调用了signalAll方法
     * 3. 发生了虚假唤醒。
     * 在所有情况下,这个方法返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,保证它持有这把锁
     * 
     * 如果当前线程在进入此方法时中断状态已被设置,或者在等待过程中被中断(例如通过调用 Thread#interrupt),它将继续等待直到被唤醒。
     * 当它最终从这个方法返回时,它的中断状态仍然会被设置。
     *
     * 实现考虑:
     * 当调用这个方法时,假设当前线程持有与此Condition关联的锁。由实现者来决定这种情况是否成立,
     * 如果不成立,应该如何响应。
     * 通常情况下,会抛出一个异常(例如IllegalMonitorStateException),并且实现者必须在文档中说明这一点。
     */
    void awaitUninterruptibly();

    /**
     * 造成线程等待,直到signalled 或者interrupted 或者过了指定的deadline 
     *
     * 与这个条件关联的锁会被原子性地释放,并且当前线程会变得不可调度,进入休眠状态,直到以下五种情况之一发生:
     * 1. 其他某个线程对这个Condition调用了signal方法,并且当前线程恰好被选中为要唤醒的线程
     * 2. 其他某个线程对这个Condition调用了signalAll方法
     * 3. 其他某个线程中断了当前线程,并且支持在挂起期间中断线程
     * 4. 指定的截止时间已过。
     * 5. 发生了虚假唤醒。
     * 在所有情况下,这个方法返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,保证它持有这把锁
     * 如果当前线程:
     * 1. 有自己的interrupted 状态设置进入这个方法
     * 2. 是interrupted在等待的时候,并且支持在挂起期间中断线程
     * 那么:
     * 抛出InterruptedException,当前线程的interrupted 状态被清除
     * 如果没有特别说明,在第一种情况下,并未指定中断检测是在释放锁之前还是之后进行
     *
     * boolean aMethod(long timeout, TimeUnit unit)
     *     throws InterruptedException {
     *   long nanosRemaining = unit.toNanos(timeout);
     *   lock.lock();
     *   try {
     *     while (!conditionBeingWaitedFor()) {
     *       if (nanosRemaining <= 0L)
     *         return false;
     *       nanosRemaining = theCondition.awaitNanos(nanosRemaining);
     *     }
     *     // ...
     *     return true;
     *   } finally {
     *     lock.unlock();
     *   }
     * }}
     * 
     * 设计说明:此方法需要一个纳秒参数,以避免在报告剩余时间时发生截断误差。
     * 这种精度损失将使得程序员难以确保在重新等待时,总的等待时间不会系统性地短于指定的时间。
     *
     * 实现考虑:
     * 1. 当调用这个方法时,假设当前线程持有与此Condition关联的锁。由实现者来决定这种情况是否成立,
     * 如果不成立,应该如何响应。
     * 通常情况下,会抛出一个异常(例如IllegalMonitorStateException),并且实现者必须在文档中说明这一点。
     *
     * 2. 实现可以选择优先响应中断,而不是正常的方法返回(响应信号)或指示指定的截止时间已过。
     * 无论哪种情况,实现都必须确保信号被重定向到另一个等待的线程(如果有其他等待的线程)。
     *
     * @param nanosTimeout 最大等待时间, 纳秒为单位
     * @return 对 nanosTimeout值减去从该方法返回时所花费的等待时间的一个估计值, 
     * 			一个正值可以作为参数用于对该方法的后续调用,以完成剩余的等待时间
     * 			如果值小于或等于零,则表示没有剩余的等待时间
     * @throws 如果当前线程被中断(并且支持中断线程挂起),则抛出InterruptedException。
     */
    long awaitNanos(long nanosTimeout) throws InterruptedException;

    /**
     * 造成线程等待,直到signalled 或者interrupted 或者过了指定的deadline 
     * awaitNanos(unit. toNanos(time)) > 0
     * 
     * @param time 最大等待时间
     * @param unit 等待时间的单位
     * @return 如果在方法返回之前明显地检测到等待时间已经过去,则返回 {@code false},否则返回 {@code true}。
     * @throws 如果当前线程被中断(并且支持中断线程挂起),则抛出InterruptedException。
     */
    boolean await(long time, TimeUnit unit) throws InterruptedException;

    /**
     * 
     * 造成线程等待,直到signalled 或者interrupted 或者过了指定的deadline 
     *
     * 与这个条件关联的锁会被原子性地释放,并且当前线程会变得不可调度,进入休眠状态,直到以下五种情况之一发生:
     * 1. 其他某个线程对这个Condition调用了signal方法,并且当前线程恰好被选中为要唤醒的线程
     * 2. 其他某个线程对这个Condition调用了signalAll方法
     * 3. 其他某个线程中断了当前线程,并且支持在挂起期间中断线程
     * 4. 指定的截止时间已过。
     * 5. 发生了虚假唤醒。
     * 在所有情况下,这个方法返回之前,当前线程必须重新获取与此条件关联的锁。当线程返回时,保证它持有这把锁
     * 如果当前线程:
     * 1. 有自己的interrupted 状态设置进入这个方法
     * 2. 是interrupted在等待的时候,并且支持在挂起期间中断线程
     * 那么:
     * 抛出InterruptedException,当前线程的interrupted 状态被清除
     * 如果没有特别说明,在第一种情况下,并未指定中断检测是在释放锁之前还是之后进行
     *
     * 返回值指示截止时间是否已经过去,可以按如下方式使用:
     * `	boolean aMethod(Date deadline)     throws InterruptedException {   
     * 			boolean stillWaiting = true;   
     * 			lock. lock();   
     * 			try {     while (!conditionBeingWaitedFor()) {       
     * 				if (!stillWaiting)         
     * 					return false;       
     * 				stillWaiting = theCondition. awaitUntil(deadline);     
     * 			}     // ...     return true;   } 
     * 		finally {     
     * 				lock. unlock();   } 
     * 		}`
     *
     * 实现考虑:
     * 1. 当调用这个方法时,假设当前线程持有与此Condition关联的锁。由实现者来决定这种情况是否成立,
     * 如果不成立,应该如何响应。
     * 通常情况下,会抛出一个异常(例如IllegalMonitorStateException),并且实现者必须在文档中说明这一点。
     * 2. 实现可以选择优先响应中断,而不是正常的方法返回(响应信号)或指示指定的截止时间已过。
     * 无论哪种情况,实现都必须确保信号被重定向到另一个等待的线程(如果有其他等待的线程)。
     *
     * @param deadline 一个线程等待直到某个特定的时间点
     * @return 如果在返回时截止时间已经过去,则返回false。否则,返回true。
     * @throws InterruptedException 如果当前线程被中断(并且支持中断线程挂起),则抛出InterruptedException。
     */
    boolean awaitUntil(Date deadline) throws InterruptedException;

    /**
     * 唤醒一个正在等待的线程
     * 1. 如果有任何线程正在等待这个条件,则选择其中一个进行唤醒。该线程在从`await`方法返回之前必须重新获取锁。 
     * 实现考虑:
     * 实现可能(通常也是这样)要求当前线程在调用此方法时持有与此`Condition`关联的锁。
     * 实现必须记录这一前提条件以及如果未持有锁时采取的任何操作。通常情况下,会抛出如`IllegalMonitorStateException`这样的异常
     */
    void signal();

    /**
     * 唤醒所有正在等待的线程。
     * 1. 如果有任何线程正在等待这个条件,则它们将全部被唤醒。每个线程在从`await`方法返回之前必须重新获取锁。
     * 实现考虑:
     * 实现可能(通常也是这样)要求当前线程在调用此方法时持有与此`Condition`关联的锁。
     * 实现必须记录这一前提条件以及如果未持有锁时采取的任何操作。通常情况下,会抛出如`IllegalMonitorStateException`这样的异常
     */
    void signalAll();
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android Profiler 内存分析

Android studio&#xff08;下面简称AS&#xff09;为App提供的性能分析工具&#xff0c;在AS3.0替换掉旧的分析工具&#xff0c;对于其使用方法&#xff0c;官方也有对应的介绍&#xff1a;Android Profiler 对于使用方法&#xff0c;我只用到比较简单的功能&#xff0c;高级的…

DXF-模型空间和图纸空间、图层冷冻标志位

‌DXF文件中操作环境的标志码是组代码67 CAD-模型空间和图纸空间-是CAD中两种不同的操作环境 模型空间主要用于建模&#xff0c;是一个没有界限的三维空间&#xff0c;用户在这个空间中以任意尺寸绘制图形&#xff0c;通常按照1&#xff1a;1的比例&#xff0c;以实际尺寸绘制…

前端开发调试之 PC 端调试

以下内容来自稀土掘金青训营课程 bug 与 debug 点击.cls开启动态修改元素的class输入字符串可以动态的给元素添加类名勾选/取消类名可以动态的查看类名生效效果点击具体的样式值&#xff08;字号、颜色、宽度高度等&#xff09;可以进行编辑&#xff0c;浏览器内容区域实时预览…

Spring Boot集成SQL Server快速入门Demo

1.什么是SQL Server&#xff1f; SQL Server是由Microsoft开发和推广的以客户/服务器&#xff08;c/s&#xff09;模式访问、使用Transact-SQL语言的关系数据库管理系统&#xff08;DBMS&#xff09;&#xff0c;它最初是由Microsoft、Sybase和Ashton-Tate三家公司共同开发的&…

Self-RAG讲解

Self-RAG Self-RAG 概述 Self-RAG&#xff08;Self-Reflective Retrieval-Augmented Generation&#xff09;是一种增强型的RAG&#xff08;检索增强生成&#xff09;策略&#xff0c;结合了自我反思和自我评分机制&#xff0c;以提高检索文档和生成内容的质量。通过对检索到…

设计一致性的关键:掌握 Axure 母版使用技巧

设计一致性的关键&#xff1a;掌握 Axure 母版使用技巧 前言 在快节奏的产品开发周期中&#xff0c;设计师们一直在寻找能够提升工作效率和保持设计一致性的方法。 Axure RP&#xff0c;作为一款强大的原型设计工具&#xff0c;其母版功能为设计师们提供了一个强大的解决方案…

uniapp框架配置项pages.json

uniapp框架配置项pages.json pages.json 文件用来对 uni-app 进行全局配置&#xff0c;决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。 globalStyle 全局配置 用于设置应用的状态栏、导航条、标题、窗口背景色等。下面配置项默认应用于每个页面。 注意…

蓝桥杯c++算法学习【1】之枚举与模拟(卡片、回文日期、赢球票、既约分数:::非常典型的比刷例题!!!)

重发一下&#xff0c;之前得排版有问题&#xff0c;而且另外加了一道题。。 别忘了请点个赞收藏关注支持一下博主喵&#xff01;&#xff01;&#xff01; 关注博主&#xff0c;更多蓝桥杯nice题目静待更新:) 枚举与模拟 一、卡片&#xff1a; 【问题描述】 小蓝有很多数字…

Java 基于 SpringBoot+Vue 的社区智慧养老系统(V3.0)

大家好&#xff0c;我是Java徐师兄&#xff0c;今天为大家带来的是Java 基于 SpringBootVue 的社区智慧养老系统&#xff08;V3.0&#xff09;。该系统采用 Java 语言开发&#xff0c;SpringBoot 框架&#xff0c;MySql 作为数据库&#xff0c;系统功能完善 &#xff0c;实用性…

el-table 纵向垂直表头处理

项目中表格展示会遇到需要纵向垂直表头情况&#xff0c;下面&#xff0c;我们基于el-table组件来实现这种表格。 以下是这次需要用到的数据表格&#xff0c;已知左侧违章名称是固定的&#xff0c;而月份是不固定的&#xff0c;在后端返回数据格式已确定的情况下&#xff0c;需…

caozha-CEPCS(新冠肺炎疫情防控系统)

caozha-CEPCS&#xff0c;是一个基于PHP开发的新冠肺炎疫情防控系统&#xff0c;CEPCS&#xff08;全称&#xff1a;COVID-19 Epidemic Prevention and Control System&#xff09;&#xff0c;可以应用于单位、企业、学校、工业园区、村落等等。小小系统&#xff0c;希望能为大…

新手如何快速搭建一个Springboot项目

新手如何快速搭建一个Springboot项目 一、开发环境准备后端其他工具 二、创建后端项目三、定义HelloController.hello()方法&#xff0c;返回“Hello Springboot” 一、开发环境准备 后端 1.安装 JDK&#xff1a;确保你的系统中安装了合适版本的 JDK&#xff0c;Spring Boot …

uniapp—android原生插件开发(4uniapp引用aar插件)

本篇文章从实战角度出发&#xff0c;将UniApp集成新大陆PDA设备RFID的全过程分为四部曲&#xff0c;涵盖环境搭建、插件开发、AAR打包、项目引入和功能调试。通过这份教程&#xff0c;轻松应对安卓原生插件开发与打包需求&#xff01; 一、将android程序打包成aar插件包 直接使…

vs2022搭建opencv开发环境

1 下载OpenCV库 https://opencv.org/ 下载对应版本然后进行安装 将bin目录添加到系统环境变量opencv\build\x64\vc16\bin 复制该路径 打开高级设置添加环境变量 vs2022新建一个空项目 修改属性添加头文件路径和库路径 修改链接器&#xff0c;将OpenCV中lib库里的o…

[Java]微服务拆分

导入项目 本篇及后续的微服务学习都是基于Centos7系统下的Docker部署&#xff0c;因此需要准备: Centos7的环境SSH客户端安装好Docker会使用Docker 之前的学习, 导致虚拟机中存在黑马商城项目以及mysql数据库, 为了保持一致, 需要删除 cd /rootdocker compose down 安装mysq…

【C++】内存池

目录 一、什么是内存池 1.池化技术 2.内存池 3.内存池主要解决的问题 二、内存池的实现 1.New申请空间 2.Delete释放空间 3.再看New申请空间 4.内存池完整代码 三、内存池性能测试 一、什么是内存池 1.池化技术 所谓 "池化技术"&#xff0c;就是程序向系统…

计算机新手练级攻略——如何搜索问题

目录 计算机学生新手练级攻略——如何搜索问题1.明确搜索意图2.使用精确关键词3.使用专业引擎搜索4.利用好技术社区1. Stack Overflow2. GitHub3. IEEE Xplore4. DBLP 5.使用代码搜索工具1. GitHub 代码搜索2. Stack Overflow 代码搜索3. Papers with Code4. IEEE Xplore 6.查阅…

区块链技术在电子政务中的应用

&#x1f493; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4dd; Gitee主页&#xff1a;瑕疵的gitee主页 ⏩ 文章专栏&#xff1a;《热点资讯》 区块链技术在电子政务中的应用 区块链技术在电子政务中的应用 区块链技术在电子政务中的应用 引言 区块链技术概述 定义与原理 发…

stm32 踩坑笔记

串口问题&#xff1a; 问题&#xff1a;会改变接收缓冲的下一个字节 串口的初始化如下&#xff0c;位长度选择了9位。因为要奇偶校验&#xff0c;要选择9位。但是接收有用数据只用到1个字节。 问题原因&#xff1a; 所以串口接收时会把下一个数据更改

034集——JIG效果实现(橡皮筋效果)(CAD—C#二次开发入门)

可实现效果如下&#xff08;对象捕捉F3需打开&#xff0c;否则效果不好&#xff09;&#xff1a; public class CircleJig : EntityJig{public static void DraCJig(){PromptPointResult ppr Z.ed.GetPoint("a");if (ppr.Value null) return;Point3d pt ppr.Value…