递归 ConcurrentHashMap.computeIfAbsent() 调用永远不会终止。错误还是“功能”?

2023-12-06

前一段时间,我在博客中介绍了一种递归计算斐波那契数的 Java 8 函数方法,有一个ConcurrentHashMap缓存和新的、有用的computeIfAbsent() method:

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class Test {
    static Map<Integer, Integer> cache = new ConcurrentHashMap<>();

    public static void main(String[] args) {
        System.out.println(
            "f(" + 8 + ") = " + fibonacci(8));
    }

    static int fibonacci(int i) {
        if (i == 0)
            return i;

        if (i == 1)
            return 1;

        return cache.computeIfAbsent(i, (key) -> {
            System.out.println(
                "Slow calculation of " + key);

            return fibonacci(i - 2) + fibonacci(i - 1);
        });
    }
}

I chose ConcurrentHashMap因为我正在考虑通过引入并行性来使这个示例变得更加复杂(我最终没有这样做)。

现在,让我们增加数量8 to 25并观察会发生什么:

        System.out.println(
            "f(" + 25 + ") = " + fibonacci(25));

程序永远不会停止。在该方法内部,有一个永远运行的循环:

for (Node<K,V>[] tab = table;;) {
    // ...
}

我在用着:

C:\Users\Lukas>java -version
java version "1.8.0_40-ea"
Java(TM) SE Runtime Environment (build 1.8.0_40-ea-b23)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)

该博文的读者 Matthias 也证实了这个问题(他确实找到了).

这很奇怪。我本来期望以下两个中的任何一个:

  • It works
  • 它抛出一个ConcurrentModificationException

但就是从不停止?这看起来很危险。这是一个错误吗?还是我误解了一些合同?


这当然是一个“特征”. The ConcurrentHashMap.computeIfAbsent()Javadoc 内容如下:

如果指定的键尚未与值关联,则尝试使用给定的映射函数计算其值并将其输入到此映射中,除非为 null。整个方法调用都是原子执行的,因此每个键最多应用该函数一次。当计算正在进行时,其他线程在此映射上尝试的一些更新操作可能会被阻止,因此计算应该简短且简单,并且不得尝试更新此映射的任何其他映射.

The “一定不”措辞是一个明确的契约,我的算法违反了它,尽管不是出于相同的并发原因。

仍然有趣的是,没有ConcurrentModificationException。相反,该程序永远不会停止——在我看来,这仍然是一个相当危险的错误(即无限循环。或者:任何可能出错的事情都会发生).

Note:

The HashMap.computeIfAbsent() or Map.computeIfAbsent()Javadoc 不禁止这种递归计算,这当然是荒谬的,因为缓存的类型是Map<Integer, Integer>, not ConcurrentHashMap<Integer, Integer>。子类型彻底重新定义超类型合约是非常危险的(Set vs. SortedSet是问候)。因此,在超类型中也应该禁止执行此类递归。

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

递归 ConcurrentHashMap.computeIfAbsent() 调用永远不会终止。错误还是“功能”? 的相关文章

  • 如何为最终用户方便地启动Java GUI程序

    用户想要从以下位置启动 Java GUI 应用程序Windows 以及一些额外的 JVM 参数 例如 javaw Djava util logging config file logging properties jar MyGUI jar
  • Java Swing:从 JOptionPane 获取文本值

    我想创建一个用于 POS 系统的新窗口 用户输入的是客户拥有的金额 并且窗口必须显示兑换金额 我是新来的JOptionPane功能 我一直在使用JAVAFX并且它是不同的 这是我的代码 public static void main Str
  • 如何在 Play java 中创建数据库线程池并使用该池进行数据库查询

    我目前正在使用 play java 并使用默认线程池进行数据库查询 但了解使用数据库线程池进行数据库查询可以使我的系统更加高效 目前我的代码是 import play libs Akka import scala concurrent Ex
  • Play框架运行应用程序问题

    每当我尝试运行使用以下命令创建的新 Web 应用程序时 我都会收到以下错误Play http www playframework org Error occurred during initialization of VM Could no
  • 使用 Android 发送 HTTP Post 请求

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

    我希望我的 Java 应用程序成为交互式 Windows 服务 用户登录时具有 GUI 的 Windows 服务 我搜索了这个 我发现这样做的方法是有两个程序 第一个是服务 第二个是 GUI 程序并使它们进行通信 服务将从 GUI 程序获取
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • Liferay ClassNotFoundException:DLFileEntryImpl

    在我的 6 1 0 Portal 实例上 带有使用 ServiceBuilder 和 DL Api 的 6 1 0 SDK Portlet 这一行 DynamicQuery query DynamicQueryFactoryUtil for
  • Mockito when().thenReturn 不必要地调用该方法

    我正在研究继承的代码 我编写了一个应该捕获 NullPointerException 的测试 因为它试图从 null 对象调用方法 Test expected NullPointerException class public void c
  • JRE 系统库 [WebSphere v6.1 JRE](未绑定)

    将项目导入 Eclipse 后 我的构建路径中出现以下错误 JRE System Library WebSphere v6 1 JRE unbound 谁知道怎么修它 右键单击项目 特性 gt Java 构建路径 gt 图书馆 gt JRE
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 仅将 char[] 的一部分复制到 String 中

    我有一个数组 char ch 我的问题如下 如何将 ch 2 到 ch 7 的值合并到字符串中 我想在不循环 char 数组的情况下实现这一点 有什么建议么 感谢您花时间回答我的问题 Use new String value offset
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 按日期对 RecyclerView 进行排序

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

    我最近开始尝试创建一个移动应用程序 iOS Android 它将自动击败比赛 http en wikipedia org wiki Beatmatching http en wikipedia org wiki Beatmatching 两
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐

  • 如何以编程方式从 Windows 手机访问 SMS 消息线程 [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我想访问 Windows Phone 上的所有消息并备份它或在 PC 手机上复制它 我搜索了这个 但无法在互联网上找到它 有没有可用的 API 来实现这一点 这仅适用于 Wind
  • Breezejs 与保存包有关的问题

    我使用breezejs 我的应用程序的服务器端代码是 net 在我看来 客户端 我想添加实体 然后我想保存它 让我们假设一个实体是这样的 Id 1 Name someName CreatedDate 1900 01 01T05 00 00Z
  • TreeView 重新获得 Ctrl+Click 的焦点

    我有一个 WinForms TreeView 控件 我想用它来根据当前选择的节点打开另一个窗体 我想在按住 Ctrl 键并单击节点时打开另一个窗体 目前 如果我在 DoubleClick 处理程序中打开另一个表单 显然是双击该节点 它就会按
  • 应用速率大于 2 倍时,avplayer 播放时出现抖动

    我想调整 Avplayer 速率 我可以在以下帮助下完成 avplayer play avplayer setRate 1 5 还禁用了音轨 低于2 0时运行良好 但当我们应用它超过 2 倍时 就会导致视频不稳定或不稳定 当我用谷歌搜索这一
  • 如何在 OpenEdge SQL 中模拟 SELECT ... LIMIT、OFFSET?

    在大多数 SQL 实现中 能够选择查询中返回的所有行的 滑动窗口 子集是很常见的事情 一个常见的用例是分页 例如 假设我有一个搜索页面 每页有 10 个结果 对于支持的实现LIMIT and OFFSET关键字 用于返回每个页面结果的查询如
  • IE8 不透明度问题

    我尝试解决IE8中出现的问题 Html 非常简单 div div div div div div div div 当我在 IE 中设置 使用 jQuery source 元素的不透明度为 0 时 我可以看到 overlay 的背景 而不是
  • 有没有办法查询未来的SSRS订阅时间表?

    在我的办公室 我们中的许多人都使用 SSRS 来安排定期报告 我想查看接下来几天或一周内即将运行的报表的时间表 以便我们可以了解 20 个报表是否都将尝试同时运行 我怎样才能做到这一点 我创建了显示订阅信息的 t sql 报告 但它们仅显示
  • 从 javascript 中的对象数组中删除重复值[重复]

    这个问题在这里已经有答案了 我有一个像这样的对象数组 arr label Alex value Ninja label Bill value Op label Cill value iopop 该数组是在渲染我的反应组件时组成的 第 i 个
  • 如何在代码中为树视图设置 WPF 数据模板?

    struct Drink public string Name get private set public int Popularity get private set public Drink string name int popul
  • C# - 使用 StreamReader 并行化 While 循环会导致 CPU 过高

    SemaphoreSlim sm new SemaphoreSlim 10 using FileStream fileStream File OpenRead using StreamReader streamReader new Stre
  • java中exec()方法的重定向

    我没有得到正确的答案 我的代码是 String s java classpath MiniRA RegAlloc lt MiniRA 4 miniIR Process pro2 Runtime getRuntime exec s Syste
  • API SurveyQuestionImage.Data 字段的正确格式是什么?

    我正在使用 GCS API 尝试使用图像数据创建调查 我在 Net 平台上使用 NuGet 包 Google Apis ConsumerSurveys v2 版本 1 14 0 564 我可以毫无问题地创建不包含图像数据的调查 但是 当我尝
  • 过滤后无法返回子类对象的Stream

    我有一个方法返回一个Stream类型的A 我也有一个亚型B of A 该方法创建一个Stream它填充了以下实例B 它们也是类型A由于继承 这工作得很好 直到我在上面引入一个过滤器Stream 然后 编译器决定 Stream 的类型B并不是
  • PHP:如何访问函数内部已在函数外部声明的变量?

    在每个页面的开头 我包含一个启动会话等的文件 我们称之为session php 在这个文件中session php 我包含一个包含函数的文件 我们称之为function1 php 因为我需要该功能可用session php 但是 稍后在主页
  • Groovy 中的类转换异常

    我想使用 grails 上的 groovy 上传图像 我的gsp页面如下 我显示的是原始的简化版本
  • XSD 断言无法识别

    我有一个 XSD 我想在其中使用xs assert陈述 问题是我不知道如何使断言功能可供我使用 我正在使用 Visual Studio 编写它 它会出现一条蓝线 表示它不支持断言元素 我的 XSD 看起来像这样
  • 检测移动浏览器

    我正在寻找一个函数 如果用户是否使用移动浏览器 该函数会返回布尔值 我知道我可以使用navigator userAgent并使用正则表达式编写该函数 但用户代理对于不同的平台来说太多样化了 我怀疑匹配所有可能的设备会很容易 而且我认为这个问
  • 多个文件是否存储在一个块中?

    当我将许多小文件存储到 HDFS 中时 它们会存储在单个块中吗 在我看来 根据此讨论 这些小文件应该存储到单个块中 HDFS 块大小与实际文件大小 引用自Hadoop 权威指南 HDFS 存储小文件效率低下 因为每个文件都存储在一个块中 并
  • Expect - 根据行和列从屏幕区域获取变量

    我正在使用 Expect 与 SSH 会话和 ERP 程序自动交互 不是依赖正则表达式来捕获我的预期脚本中的变量 是否可以在收到用户的特定击键后将屏幕区域 例如一个字段 捕获到代码中的变量中 向服务器发送一些其他命令并重新发送该字段 假设订
  • 递归 ConcurrentHashMap.computeIfAbsent() 调用永远不会终止。错误还是“功能”?

    前一段时间 我在博客中介绍了一种递归计算斐波那契数的 Java 8 函数方法 有一个ConcurrentHashMap缓存和新的 有用的computeIfAbsent method import java util Map import j