返回一个 CompletableFuture 而不暴露执行器线程

2024-02-05

我在库中公开了一个方法,该方法返回一个 CompletableFuture。该方法的计算发生在单线程执行器上,这是我的瓶颈,因此我不希望任何后续工作发生在同一线程上。

如果我使用返回“supplyAsync”结果的简单方法,我会将我宝贵的线程暴露给调用者,调用者可能会添加同步操作(例如通过 thenAccept),这可能会在该线程上占用一些 CPU 时间。

重现如下:

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CfPlayground {
    private ExecutorService preciousExecService = Executors.newFixedThreadPool(1);

    CfPlayground() {}

    private static void log(String msg) {
        System.out.println("[" + Thread.currentThread().getName() + "] " + msg);
    }

    CompletableFuture<String> asyncOp(String param) {
        return CompletableFuture.supplyAsync(() -> {
            log("In asyncOp");
            return "Hello " + param;
        }, preciousExecService);
    }

    void syncOp(String salutation) {
        log("In syncOp: " + salutation);
    }

    void run() {
        log("run");
        asyncOp("world").thenAccept(this::syncOp);
    }

    public static void main(String[] args) throws InterruptedException {
        CfPlayground compFuture = new CfPlayground();
        compFuture.run();
        Thread.sleep(500);
        compFuture.preciousExecService.shutdown();
    }
}

这确实打印:

[main] run
[pool-1-thread-1] In asyncOp
[pool-1-thread-1] In syncOp: Hello world

我发现的一个解决方案是引入另一个执行器,并在返回 CompletableFuture 之前添加一个无操作 thenApplyAsync 与该执行器

    CompletableFuture<String> asyncOp(String param) {
        return CompletableFuture.supplyAsync(() -> {
            log("In asyncOp");
            return "Hello " + param;
        }, preciousExecService).thenApplyAsync(s -> s, secondExecService);
    }

这可行,但感觉不太优雅——有更好的方法吗?


没有任何功能可以将您的完成与相关操作的执行分离。当链接依赖操作的线程已经完成注册并且执行器的线程完成未来时,如果没有给出其他执行器,哪个其他线程应该执行依赖操作?

您将另一个操作与不同的执行者链接起来的方法似乎是您能得到的最好的方法。然而,值得注意的是,如果发生异常完成,异常会在不评估传递给的函数的情况下传播thenApply。如果调用者链接了类似的操作,则此异常传播可能再次导致线程暴露whenComplete, handle, or exceptionally.

另一方面,您不需要指定辅助执行程序,因为您可以使用async不带 executor 参数的方法,获取默认(通用 Fork/Join)池。

所以链接.whenCompleteAsync((x,y) -> {})是迄今为止解决您问题的最佳方案。

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

返回一个 CompletableFuture 而不暴露执行器线程 的相关文章

  • CompletableFuture:whenCompleteAsync() 不允许我重新抛出异常

    我是 CompletableFuture 世界的新手 我正在尝试做一些负面测试 以允许我故意抛出异常的方式 该异常将决定通过 失败 这是代码片段 protected CompletableFuture
  • 如何修复安装 maven jar 插件依赖项时出现的错误?

    我正在将应用程序制作成 maven 中的 jar 文件 但是 当我从 Maven 中提取 jar 插件存储库并在终端中运行这三个命令时 mvn clean mvn compile mvn package 在 mvn package 中 我收
  • Java 8 中异常类型推断的一个独特功能

    在为该网站上的另一个答案编写代码时 我遇到了这个特性 static void testSneaky final Exception e new Exception sneakyThrow e no problems here nonSnea
  • JTree 避免重新加载后崩溃

    我正在尝试找到解决崩溃问题的方法JTree重新加载后 情况 JTree Office A Office A 1 Office A 1 1 Office A 1 2 Office B Office B 1 Office B 1 1 Offic
  • 打印数组时出错

    我得到这个代码 import java util import java io public class Oblig3A public static void main String args OrdAnalyse O new OrdAna
  • Logback 配置在单行上有异常吗?

    我的日志被提取 传输并合并到 elasticsearch 中 多行事件很难跟踪和诊断 有没有办法使用收集器和正则表达式将异常行分组到单个记录中登录配置 https logback qos ch manual layouts html xTh
  • 声纳要求将这一领域定为最终目标

    我的程序中有以下代码 在与 Maven 集成后 我正在运行 SonarQube 5 对其进行代码质量检查 我面临这个错误 将此 public static processStatus 字段设为最终字段 将此 public static pr
  • 最终类中的静态函数是否隐式最终?

    我的问题基本上与this https stackoverflow com q 8766476 3882565一 但这是否也适用于static功能 我想了解 编译器是否处理所有static函数在一个final类为final 是否添加final
  • MongoDb Spring 在嵌套对象中查找

    我正在使用 Spring Data Mongodb 和这样的文档 id ObjectId 565c5ed433a140520cdedd7f attributes 565c5ed433a140520cdedd73 333563851 list
  • SQLite 64位整数在jooq中被识别为int

    我有一个与 jOOQ 一起使用的 SQLite 数据库 当我使用 jOOQ 的代码生成工具时 它会按预期构建所有表和记录类 然而 所有的 SQLiteINTEGER列变成java lang Integer生成的代码中的字段 问题是 SQLi
  • Spring Boot - 如何在开发过程中禁用@Cacheable?

    我正在寻找两件事 如何在开发过程中使用 Spring boot dev 配置文件禁用所有缓存 application properties 中似乎没有通用设置可以将其全部关闭 最简单的方法是什么 如何禁用特定方法的缓存 我尝试像这样使用 S
  • 如何保存/加载 BigInteger 数组

    我想保存 加载BigInteger数组传入 传出 SharedPreferences 如何做呢 例如对于以下数组 private BigInteger dataCreatedTimes new BigInteger 20 Using Gso
  • 抛出 UnsupportedOperationException

    因此其中一种方法的描述如下 public BasicLinkedList addToFront T data 该操作无效 对于排序列表 将生成 UnsupportedOperationException 使用消息 排序列表的操作无效 我的代
  • 使用mapstruct映射不同类型列表的元素

    我们正在映射一个对象 该对象具有一个对象列表 这些对象都实现了父接口 但可能具有不同的实现 但当我们映射列表时 似乎只有来自 ParentClass 的值被映射 而不是来自子类的值 但直接映射子进程就可以了 public class Par
  • 当 javadoc 未附加到依赖项时,如何将 javadoc 引用到 Maven 的 eclipse 插件中的依赖项

    我在开发中使用 Eclipse Maven 和 Java 我使用 Maven 下载依赖项 jar 文件和 javadoc 如果可用 并使用 Maven 的 eclipse 插件为 Eclipse 生成 project 和 classpath
  • 如何强制 Spark 执行代码?

    我如何强制 Spark 执行对 map 的调用 即使它认为由于其惰性求值而不需要执行它 我试过把cache 与地图调用 但这仍然没有解决问题 我的地图方法实际上将结果上传到 HDFS 所以 它并非无用 但 Spark 认为它是无用的 简短回
  • 如何在java中进行多处理,以及预期的速度提升是多少?

    我是一个新手 使用 Java 对 csv 文件进行一些数据处理 为此 我使用 Java 的多线程功能 线程池 将 csv 文件批量导入到 Java 中 并对每一行执行一些操作 在我的四核处理器上 多线程大大加快了处理速度 我很想知道多处理如
  • 最新版本 6.* Struts2 支持 Tomcat 10 吗? [复制]

    这个问题在这里已经有答案了 最新版本 6 Struts2 支持 Tomcat 10 吗 异常启动过滤器 struts2 java lang ClassCastException class org apache struts2 dispat
  • Encog:BasicNetwork:无需预先构建数据集的在线学习

    我正在尝试使用 encog 库作为强化学习问题的函数逼近器 更准确地说 我正在尝试启动并运行多层感知器 BasicNetwork 由于我的代理将根据我选择的任何 RL 算法以某种方式探索世界 因此我无法预先构建任何 BasicNeuralD
  • Java GridBagConstraints gridx 和 gridy 不工作?

    我正在尝试使用gridx and gridy定位我的按钮的约束 但它们不起作用 如果我改变gridx and gridy变量 什么也没有发生 如果我将填充更改为GridBagConstraints to NONE 仍然不行 我在这里错过了什

随机推荐