为什么我的 CompletableFuture 代码可以在 Java 8 中运行,但不能在 Java 11 中运行?

2024-03-27

为什么这段代码在 Java 8 和 Java 11 中的行为不同?

private static String test2() {
    CompletableFuture
            .runAsync(() -> IntStream.rangeClosed(1, 20).forEach(x -> {
                try {
                    Thread.sleep(500);
                    System.out.println(x);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }));

    return "Finish";
}

我期望它打印 Finish,然后对于从 1 到 20 的数字,以 500 毫秒的间隔打印该数字,然后停止执行,并且它在 Java 8 中正常工作。

然而,当我在 Java 11 上运行完全相同的方法时,它打印 Finish 并终止,而没有调用 runAsync(...) 代码。我设法通过添加这样的 ExecutorService 来启动它

private static String test2() {

    final ExecutorService executorService = Executors.newFixedThreadPool(10);
    CompletableFuture
            .runAsync(() -> IntStream.rangeClosed(1, 10).forEach(x -> {
                try {
                    Thread.sleep(500);
                    System.out.println(x);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }), executorService);

    return "Finish";
}

现在它被执行了,但还没有完成;它达到了 10,之后就一直坐着而没有完成。我想出了如何通过调用来停止执行executorService.shutdown();就在返回之前,但我 100% 确定这种方法是错误的,因为通常我会对许多方法使用相同的 executorService,并且如果我将其关闭,其他方法也将无法执行。

Java 8 和 Java 11 之间发生了什么变化,为什么我现在必须添加显式执行器服务,最重要的是如何正确完成方法执行?


TL;DR - add ForkJoinPool.commonPool().awaitQuiescence(1000, TimeUnit.SECONDS);在您致电后CompletableFuture.runAsync 并在代码末尾以便System.exit不会停止你的可运行程序。这样你就会得到你的行为。


更长的答案:

好的,首先,我在 Oracles java 8、OpenJDK 8 和 OpenJDK 11 中尝试了这两个示例。全面一致的行为,所以我的答案是nothing不同java版本的这些实现发生了变化,这会导致这种差异。在both例如,您看到的行为与 Java 告诉您它将执行的行为一致。

从文档CompletableFuture.runAsync

返回一个新的 CompletableFuture,它由运行在中的任务异步完成ForkJoinPool.commonPool()在运行给定的操作之后。

好吧...让我们看看是什么ForkJoinPool.commonPool会告诉我们(强调我的):

返回公共池实例。该池是静态构建的;它的运行状态不受尝试的影响shutdown() or shutdownNow(). 然而,该池和任何正在进行的处理都会根据程序自动终止System.exit(int)。任何程序依赖于异步任务处理在程序终止应调用之前完成commonPool().awaitQuiescence,退出之前。

啊哈,这就是为什么我们在使用公共池时看不到倒计时,因为公共池将在系统退出时终止,这正是我们从方法返回并退出程序时发生的情况(假设您的示例是正如您所展示的那样,真的很简单...就像调用单个方法一样main... 无论如何)

那么为什么自定义执行器会起作用呢?因为,正如您已经注意到的那样,该执行程序尚未终止。后台仍然有一段代码在运行,尽管是闲置的,但 Java 没有能力停止。


那么我们现在能做什么呢?

One选择是做我们自己的执行程序并在完成后将其关闭,就像您所建议的那样。我认为这种方法isn't终究不好用。

Second选项是遵循 java doc 的说明。

任何依赖异步任务处理在程序终止之前完成的程序都应该调用commonPool().awaitQuiescence,退出之前。

公共布尔等待静止(长时间超时, TimeUnit 单位)

如果由在此池中运行的 ForkJoinTask 调用,则等效于 ForkJoinTask.helpQuiesce()。否则,等待和/或尝试协助执行任务,直到该池 isQuiescent() 或指示的超时过去。

因此,我们可以调用该方法并为公共池中的所有公共进程指定超时。我的看法是,这有点业务特定,从现在开始你必须回答这个问题 -现在超时到底应该是什么?.

Third选项是使用的力量CompletableFutures 并吊起这个runAsync变量的方法:

CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> ...
...
...
bla bla bla code bla bla bla
...
...
voidCompletableFuture.join();
// or if you want to handle exceptions, use get
voidCompletableFuture.get();

然后当你需要它的时候,你join()/get()无论你需要什么作为返回值。我最喜欢这个,因为这样的代码是最干净、最容易理解的。我也可以chain我的 CF 有我想要的一切,并可以用它们做一些时髦的事情。


在这种情况下你不需要返回值,也不需要做任何其他事情,只想要一个简单的字符串返回和从 1 到 20 的异步处理,然后只需推ForkJoinPool.commonPool().awaitQuiescence(1000, TimeUnit.SECONDS);在你方便的地方并给它一些荒谬的超时,因此保证你将退出所有人idle流程。

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

为什么我的 CompletableFuture 代码可以在 Java 8 中运行,但不能在 Java 11 中运行? 的相关文章

  • .java 和 .scala 类之间是否可能存在循环依赖?

    假设我在 java 文件中定义了类 A 在 scala 文件中定义了类 B A 类使用 B 类 B 类使用 A 类 如果我使用 java 编译器 则会出现编译错误 因为 B 类尚未编译 如果我使用scala编译器A类将找不到 有没有可以同时
  • 有效地查找正则表达式的所有重叠匹配项

    这是后续与 java 正则表达式匹配的所有重叠子字符串 https stackoverflow com q 11303309 244526 有没有办法让这段代码更快 public static void allMatches String
  • 运行多线程时双重释放或损坏

    我在 C 程序中遇到运行时错误 双重释放或损坏 该程序调用可靠的库 ANN 并使用 OpenMP 并行化 for 循环 glibc detected home tim test debug test double free or corru
  • 判断线程是否已经启动

    如何判断Python线程是否已经启动 有一个方法is alive 但这是真的before and while一个线程正在运行 你可以看看ident领域的Thread实例 这Python 2 7 线程文档 http docs python o
  • 删除 servlet 中的 cookie 时出现问题

    我尝试使用以下代码删除 servlet 中的 cookie Cookie minIdCookie null for Cookie c req getCookies if c getName equals iPlanetDirectoryPr
  • 如何在 OpenAPI 3.0 中定义字节数组

    我正在将 API 从 Swagger 2 0 迁移到 OpenAPI 3 0 在 DTO 中 我有一个指定为字节数组的字段 Swagger 对 DTO 的定义 Job type object properties body type str
  • 如何正确配置Tomcat SSLHostConfig?

    我正在按照本教程在 tomcat 中启用 ssl https medium com raupach how to install lets encrypt with tomcat 3db8a469e3d2 https medium com
  • firestore快照监听器生命周期和定价之间有什么关系?

    在我的活动中 我有一个字符串列表 这些字符串表示我想要附加快照侦听器的 Firestore 文档 我使用 Acivity ModelView 存储库结构 在活动的 onCreate 中 我向 ViewModelProvider 询问适当的
  • 业务代表与服务定位器

    Business Delegate 和 Service Locator 之间有什么区别 两者都负责封装查找和创建机制 如果 Business Delegate 使用 Service Locator 来隐藏查找和创建机制 那么 Busines
  • 如何消除警告:使用“$”而不是“.”对于 Eclipse 中的内部类

    我是 Android 开发新手 当我将 eclipse 和 Android SDK 更新到最新版本后 我收到警告 Use instead of for inner classes or use only lowercase letters
  • 独占锁定ConcurrentHashMap

    我知道不可能锁定 ConcurrentHashMap 进行独占访问 但是 我找不到原因 是因为构成CHM的 Segment 没有被api公开吗 据推测 如果是的话 客户端代码可以执行 交接 锁定 Cheers 我知道不可能锁定 Concur
  • getClassLoader().getResource() 返回 null

    我有这个测试应用程序 import java applet import java awt import java net URL public class Test extends Applet public void init URL
  • 通用 JSF 实体转换器[重复]

    这个问题在这里已经有答案了 我正在编写我的第一个 Java EE 6 Web 应用程序作为学习练习 我没有使用框架 只是使用 JPA 2 0 EJB 3 1 和 JSF 2 0 我有一个自定义转换器 用于将存储在 SelectOne 组件中
  • 当容器大小更改时,JTable 仅调整选定列的大小

    对于面板内的 JTable 如果面板变大 我如何将额外的空间仅分配给某些列 在我的例子中 分配给最后一列 尽管提供 第 3 4 列和8 将获得额外的空间 我想允许用户手动更改所有列的列大小 我尝试了 table setAutoResizeM
  • Android同步onSensorChanged?

    这是我的问题的后续 Android线程可运行性能 https stackoverflow com questions 36395440 android thread runnable performance 我在理解应用程序的同步方法时遇到
  • Java SE + Spring Data + Hibernate

    我正在尝试使用 Spring Data Hibernate 启动 Java SE 应用程序 并且到目前为止已经完成了以下操作 配置文件 Configuration PropertySource classpath hibernate pro
  • Java的hashCode可以为不同的字符串产生相同的值吗?

    使用java的哈希码函数是否可以为不同的字符串提供相同的哈希码 或者如果可能的话 其可能性的 是多少 Java 哈希码是 32 位 它散列的可能字符串的数量是无限的 所以是的 会发生冲突 百分比是没有意义的 项目 字符串 的数量是无限的 而
  • 日期时间解析异常

    解析日期时 我的代码中不断出现异常错误 日期看起来像这样 Wed May 21 00 00 00 EDT 2008 这是尝试读取它的代码 DateTimeFormatter formatter DateTimeFormatter ofPat
  • Java 9 中紧凑字符串和压缩字符串的区别

    有什么优点紧凑的字符串 http openjdk java net jeps 254JDK9 中的压缩字符串 压缩字符串 Java 6 和紧凑字符串 Java 9 都有相同的动机 字符串通常实际上是 Latin 1 因此浪费了一半的空间 和
  • 如何使用 Spring AOP 建议静态方法?

    在执行类的静态方法之前和之后需要完成一些日志记录 我尝试使用 Spring AOP 来实现这一点 但它不起作用 而对于正常方法来说它起作用 请帮助我理解如何实现这一点 如果可以使用注释来完成 那就太好了 也许您应该在使用 Spring AO

随机推荐

  • 手臂 g++ 中缺少一些东西

    我安装了 CodeSourcery g 工具链并尝试编译一个简单的 hello world 程序 include
  • 我的 PDO 构造错误 - Php

    这是6号线的抱怨声 Warning PDO construct expects parameter 2 to be string array given 伴随着第 7 行错误 Fatal error Call to a member fun
  • 二维数组的按行 numpy.isin [重复]

    这个问题在这里已经有答案了 我有两个数组 A np array 3 1 4 1 1 4 B np array 0 1 5 2 4 5 2 3 5 是否可以使用numpy isin二维数组按行排列 我想检查一下是否A i j is in B
  • 使用用户定义的运行时属性的 UILabel 的cornerRadius 不起作用

    我尝试使用将cornerRadius添加到UILabelUser Defined Runtime Attributes但它没有按预期工作 cornerRadius 没有设置 我想知道我在哪里犯了错误 我附上了它的截图 帮我解决一下 It i
  • JavaScript 中的构造函数和继承

    这是关于 JavaScript 中的 继承 假设我创建一个构造函数 Bird 和另一个名为 Parrot 的构造函数 通过将 Bird 的实例分配给 Parrot 的原型来 继承 Bird 的属性 如以下代码所示 function Bird
  • 使用前缀路由时 url 中的 CakePHP3.x 控制器名称

    我正在尝试在 CakePHP3 中使用前缀路由 我将以下几行添加到 config routes php Router prefix admin function routes All routes here will be prefixed
  • Prefuse:向 GraphView 演示添加边权重

    我正在使用 prefuse 可视化工具包 工具包中的 GraphView 演示非常出色 提供了各种控件来可视化数据 我能够为我的数据集生成 GraphML 并使用 GraphView 对其进行可视化 我希望拥有的另一件事是使用权重或颜色编码
  • Elasticsearch:使用 Java 添加手动映射

    我无法更改映射 有人能帮我找到代码中的错误吗 我根据几个教程找到了更改映射的标准方法 但是 当我尝试调用映射结构时 在手动创建映射后只会出现一个空白映射结构 但是插入一些数据后就会出现映射规范 因为ES当然使用默认的映射规范 更具体的请看下
  • Php $_POST方法获取textarea值

    我正在使用 php 使用 post 方法获取 textarea 值 但得到一个奇怪的结果 让我向你展示我的代码
  • 在没有 VSDBCMD 的情况下部署 VS2010 数据库项目?

    自首次引入 Visual Studio 2010 的数据库项目以来 我们一直在多个内部或单一客户项目中使用它们 到目前为止 它们对我们来说运行良好 现在 我们第一次将它们与 盒装 产品一起使用 该产品需要打包才能安装在任意客户站点 到目前为
  • 可靠的WebSocket连接状态检测

    我一直在寻找实现可靠的 WebSocket 连接恢复机制 经过一番调查 我发现一种方法是将心跳发送到服务器 ping pong 并检查我是否收到整个pong在有限的时间内 因此 如果连接实际上已断开或速度非常慢 则会被视为断开连接 if a
  • 如何修复IntelliJ IDEA方法参数自动完成?

    我正在使用 IntelliJ IDEA 15 我注意到 默认情况下 Eclipse 在编写需要多个参数的方法调用时提供了更方便的自动完成功能 Eclipse 会自动填充默认参数 并允许您通过按快速浏览它们Tab IntelliJ 不这样做
  • 打印转换后的 XML

    由于情况超出了我的控制范围 我将用自制的 XML 报告替换所有的 Crystal 报告 这些报告运行得非常好 对于大多数弹出 Crystal Reports 查看器的报表 以下代码可以在 IE 中很好地打开它们 并通过 XSLT 样式表将其
  • DRF Serializer - 如何返回外键字段?

    早上好 我真的很难解决从 Django Rest Framework API 返回值的问题 我有两个模型 SirTarget 和 Status SirTarget 就像一张票证 而 Status 是票证的文本状态标签 对应于处理票证的阶段
  • 来自 Properties 的 C# 自定义属性

    所以我有一个来自我的类 的属性集合 我想循环遍历它 对于每个属性 我可能有自定义属性 因此我想循环遍历这些属性 在这种特殊情况下 我的城市类别有一个自定义属性 public class City ColumnName OtroID publ
  • Swift / SKStoreProductViewController PushViewController 结果为(lldb)

    为了将用户推送到 iTunes 商店获取所需的项目 我使用以下函数 func openStoreProductWithiTunesItemIdentifier identifier String let storeViewControlle
  • 使用 pytest-django 进行测试期间,Django 连接对象看不到第二个数据库的表

    底线 在使用 pytest django 进行测试期间 我的 Django 连接对象看不到第二个数据库的表关系 概述 我有一个问题 我的 Django 连接对象似乎获取了错误的数据库信息 当我查询 客户 数据库中的表时 我偶然发现了这个问题
  • 文本编辑器的动态高度

    我正在努力适应TextEditor里面一个ScrollView 有没有办法制作TextEditor只占用适合所有文本所需的空间 或者简单地说 如何改变height of the TextEditor动态地适应所有文本 你可以把它放在一个ZS
  • 取消 AJAX 请求会减慢后续导航速度

    在我的应用程序中 当用户请求报告时 jquery AJAX 使用 load 调用一个执行大量数字运算和 mySQL 请求的文件 加载一般需要5 6秒 ajaxStart and ajaxStop 用于在加载期间显示加载 gif 问题 如果用
  • 为什么我的 CompletableFuture 代码可以在 Java 8 中运行,但不能在 Java 11 中运行?

    为什么这段代码在 Java 8 和 Java 11 中的行为不同 private static String test2 CompletableFuture runAsync gt IntStream rangeClosed 1 20 fo