java中使用wait()和notify()的简单场景

2023-12-28

我可以获得一个完整的简单场景,即建议如何使用它的教程,特别是使用队列?


The wait() and notify()方法旨在提供一种机制,允许线程阻塞直到满足特定条件。为此,我假设您想要编写一个阻塞队列实现,其中有一些固定大小的元素后备存储。

您要做的第一件事是确定您希望方法等待的条件。在这种情况下,您将需要put()方法进行阻塞,直到存储中有可用空间,并且您将需要take()方法阻塞,直到有一些元素要返回。

public class BlockingQueue<T> {

    private Queue<T> queue = new LinkedList<T>();
    private int capacity;

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public synchronized void put(T element) throws InterruptedException {
        while(queue.size() == capacity) {
            wait();
        }

        queue.add(element);
        notify(); // notifyAll() for multiple producer/consumer threads
    }

    public synchronized T take() throws InterruptedException {
        while(queue.isEmpty()) {
            wait();
        }

        T item = queue.remove();
        notify(); // notifyAll() for multiple producer/consumer threads
        return item;
    }
}

关于使用等待和通知机制的方式,有几点需要注意。

首先,您需要确保任何调用wait() or notify()位于代码的同步区域内(带有wait() and notify()在同一对象上同步调用)。造成这种情况的原因(除了标准线程安全问题之外)是由于丢失信号造成的。

一个例子是,线程可以调用put()当队列碰巧已满时,它会检查条件,发现队列已满,但在它可以阻止另一个线程被调度之前。然后第二个线程take()是队列中的一个元素,并通知等待线程队列不再满。然而,因为第一个线程已经检查了条件,所以它只会调用wait()重新安排后,尽管可以取得进展。

通过在共享对象上同步,您可以确保不会发生此问题,因为第二个线程的take()在第一个线程实际阻塞之前,调用将无法取得进展。

其次,由于存在虚假唤醒问题,您需要将要检查的条件放入 while 循环中,而不是 if 语句中。这是有时可以重新激活等待线程而无需notify()被召唤。将此检查放在 while 循环中将确保如果发生虚假唤醒,将重新检查条件,并且线程将调用wait() again.


正如其他一些答案所提到的,Java 1.5 引入了一个新的并发库(在java.util.concurrent包),旨在为等待/通知机制提供更高级别的抽象。使用这些新功能,您可以像这样重写原始示例:

public class BlockingQueue<T> {

    private Queue<T> queue = new LinkedList<T>();
    private int capacity;
    private Lock lock = new ReentrantLock();
    private Condition notFull = lock.newCondition();
    private Condition notEmpty = lock.newCondition();

    public BlockingQueue(int capacity) {
        this.capacity = capacity;
    }

    public void put(T element) throws InterruptedException {
        lock.lock();
        try {
            while(queue.size() == capacity) {
                notFull.await();
            }

            queue.add(element);
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public T take() throws InterruptedException {
        lock.lock();
        try {
            while(queue.isEmpty()) {
                notEmpty.await();
            }

            T item = queue.remove();
            notFull.signal();
            return item;
        } finally {
            lock.unlock();
        }
    }
}

当然,如果您确实需要一个阻塞队列,那么您应该使用阻塞队列 http://java.sun.com/javase/6/docs/api/java/util/concurrent/BlockingQueue.html界面。

另外,对于这样的东西我强烈推荐Java 并发实践 http://www.amazon.co.uk/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601,因为它涵盖了您可能想了解的有关并发相关问题和解决方案的所有内容。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java中使用wait()和notify()的简单场景 的相关文章

  • java.lang.NoClassDefFoundError:org.apache.batik.dom.svg.SVGDOMImplementation

    我在链接到我的 Android LibGDX 项目的 Apache Batik 库时遇到了奇怪的问题 但让我们从头开始 在 IntelliJ Idea 中我有一个项目 其中包含三个模块 Main Android 和 Desktop 我强调的
  • Java new Date() 打印

    刚刚学习 Java 我知道这可能听起来很愚蠢 但我不得不问 System out print new Date 我知道参数中的任何内容都会转换为字符串 最终值是 new Date 返回对 Date 对象的引用 那么它是如何打印这个的呢 Mo
  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 使用 Android 发送 HTTP Post 请求

    我一直在尝试从 SO 和其他网站上的大量示例中学习 但我无法弄清楚为什么我编写的示例不起作用 我正在构建一个小型概念验证应用程序 它可以识别语音并将其 文本 作为 POST 请求发送到 node js 服务器 我已确认语音识别有效 并且服务
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • 控制Android的前置LED灯

    我试图在用户按下某个按钮时在前面的 LED 上实现 1 秒红色闪烁 但我很难找到有关如何访问和使用前置 LED 的文档 教程甚至代码示例 我的意思是位于 自拍 相机和触摸屏附近的 LED 我已经看到了使用手电筒和相机类 已弃用 的示例 但我
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 磁模拟

    假设我在 n m 像素的 2D 表面上有 p 个节点 我希望这些节点相互吸引 使得它们相距越远吸引力就越强 但是 如果两个节点之间的距离 比如 d A B 小于某个阈值 比如 k 那么它们就会开始排斥 谁能让我开始编写一些关于如何随时间更新
  • 如何在PreferenceActivity中添加工具栏

    我已经使用首选项创建了应用程序设置 但我注意到 我的 PreferenceActivity 中没有工具栏 如何将工具栏添加到我的 PreferenceActivity 中 My code 我的 pref xml
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 如何为俚语和表情符号构建正则表达式 (regex)

    我需要构建一个正则表达式来匹配俚语 即 lol lmao imo 等 和表情符号 即 P 等 我按照以下示例进行操作http www coderanch com t 497238 java java Regular Expression D
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • 按日期对 RecyclerView 进行排序

    我正在尝试按日期对 RecyclerView 进行排序 但我尝试了太多的事情 我不知道现在该尝试什么 问题就出在这条线上适配器 notifyDataSetChanged 因为如果我不放 不会显示错误 但也不会更新 recyclerview
  • 节拍匹配算法

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两

随机推荐

  • iPython - 在配置文件中设置魔法命令

    我主要通过笔记本使用 iPython 但也在终端中使用 我刚刚通过运行创建了我的默认配置文件ipython profile create 我似乎无法弄清楚如何让配置文件运行我每次使用的几个神奇命令 我试图在网上和我正在读的书中查找这一点 但
  • 如何使用 Spring Data 获取数据

    嘿 我想创建一个扩展 JpaRepository 的存储库并获取结果而不编写实际查询 在我的示例中 我有 2 个表 Book 和 Author 通过多对多关系映射 假设我想按特定的author id 获取书籍列表 因为在我的书籍实体中 我没
  • 无法在 Vim 中映射

    周末拿到了我的第一台 Mac 我正在努力适应 我的 vimrc 中的这一行在我的 Windows 上有效 但无法通过 iTerm 与 vim 一起工作 inoremap
  • 具有约束关联类型错误“类型不可转换”的 Swift 协议

    我创建了 2 个具有关联类型的协议 类型符合Reader应该能够生成符合以下类型的实例Value 复杂性层来自于符合以下条件的类型Manager应该能够生产混凝土Reader产生特定类型的实例Value 任何一个Value1 or Valu
  • */ 中 d 的 shell 脚本; do在本地运行,但在circleci中不起作用

    我构建了一个脚本 当我尝试在本地运行它时 它工作正常 但是当我在 Circleci 上运行它时 我收到错误 这是脚本 usr bin env bash for d in do cd d for f in do if f sh then if
  • 提示用户打开另一个工作簿

    我正在编写一个子程序 我需要用户打开特定的工作簿 因为我需要将数据从将打开的工作簿复制到运行该子程序的工作簿 由于将打开的文件是月度报告 因此用户很难始终将其以相同的文件名保存在同一位置 因此 如果要求用户打开工作簿 月度报告 那就太好了
  • VS Code 自动导入不使用绝对路径且不缩进

    我将 Typescript 与 SvelteKit 结合使用 当我输入可以自动导入的内容时 如上面的 GIF 所示 自动导入不会使内容保持相同的缩进级别 我还需要绝对路径 src not src VS 代码的设置称为 TypeScript
  • Magento 报告 - 产品 - 产品订购问题:具有相同 ID 的项目 (Mage_Catalog_Model_Product) 已存在

    问题 在 Magento 管理面板中 通过 报告 产品 订购的产品 生成报告时 会发生错误 Item Mage Catalog Model Product with the same id 45 already exist 0 home g
  • 读取文件中的每一行并将每一行放入一个字符串中

    我有一个文本文件 我想读入该文件并将文件中的每一行放入其自己的字符串中 所以该文件将有 4 行 2017 01 2005 59 30 353879833382971575 迈克尔 因此 在代码中 我需要读取文件并拆分每一行并将它们放入一个字
  • 垂直错开 div

    有没有办法像这张图片一样以交错的垂直排列方式显示 div 到目前为止 我已经使用 Flexbox 来接近 但无法交错行 因为我不想预先确定每行有多少个圆圈 我希望用户的浏览器宽度来控制每行有多少个圆圈 因此圆圈 div 上没有类或子项 随着
  • Play框架 路由不区分大小写

    我们目前正在开发 Play 2 5 x 我们希望实现不区分大小写的路由 比如说 GET via v1 organizations http organizationApi 在我们想要实现的URL中 http localhost 9000 a
  • MFC不支持小于0x0501的WINVER

    我有一个 C 项目引用了许多其他项目 库 这是针对多年前创建的应用程序 大约每年更新一次并完成新版本 我多年来一直使用 Visual Studio 6 更新和构建此应用程序的新版本 没有出现任何问题 我正在尝试切换到 Visual Stud
  • Python NLTK 多线程

    我正在编写一个算法 它可以识别给定文本中的句子 将每个句子拆分成单词并在经过一些验证后返回这些单词 我想在多线程的帮助下实现同样的功能 我正在调用处理每个句子的函数threading thread 它会抛出一个错误 AttributeErr
  • 如何在javascript中获取最高的输入字段值

    我想获得这个领域的最高价值 我怎样才能做到这一点
  • “始终开启”设置会阻止idleTimeout 和periodicRestart 吗?

    您可能知道 Microsoft Azure 网站服务下托管的网站默认配置为空闲 20 分钟后超时 idleTimeout 并且应用程序池每 29 小时重新启动一次 periodicRestart 这会导致第一个用户访问网站时速度很慢 我想知
  • 将 Recaptcha 与 EPiServer XForms 结合使用

    有人有在 EPiServer 中使用 Recaptcha 和 XForms 的经验吗 我不知道将 Recaptcha 控件放在哪里以及如何使其工作 ASP NET 的示例代码如下 我应该把它放在哪里 我的猜测是在FormControl Be
  • 多态推理

    我正在学习 Haskell 在互联网上我发现的是paper https people mpi sws org dreyer tor papers wadler pdf来自菲利普 瓦德勒 我读了它 但根本不明白 但它以某种方式与多态函数联系起
  • Internet Explorer CSS 问题

    This page http a accioly 7rtc com p tecnologia htmlIE 9 也可能是旧版本 无法正确呈现 右侧菜单浮动到页面底部 Firefox Chrome 和 Safari 可以正确渲染它 所有浏览器
  • DispatchQueue :无法在非主线程上使用 asCopy = NO 进行调用

    我正在介绍的是UIAlertController在主线程上为 class HelperMethodClass NSObject class func showAlertMessage message String viewControlle
  • java中使用wait()和notify()的简单场景

    我可以获得一个完整的简单场景 即建议如何使用它的教程 特别是使用队列 The wait and notify 方法旨在提供一种机制 允许线程阻塞直到满足特定条件 为此 我假设您想要编写一个阻塞队列实现 其中有一些固定大小的元素后备存储 您要