Java 21 中的 CompletableFuture 与虚拟线程

随着 Java 21 的发布,虚拟线程被引入作为可完成的 future 和线程的替代并发模型。可完成的 future 和虚拟线程都旨在简化 Java 中的异步编程,但采取了不同的方法。本文探讨了两者之间的主要区别。

什么是CompletableFutures?

CompletableFuture 是 Java 8 中添加的一个类,表示可以产生结果或异常完成的异步计算。它实现了 Future 接口,并提供了手动完成 future、等待完成、注册回调以及将可计算阶段链接在一起的方法。

CompletableFuture 的主要特点:

  • 异步操作------等待结果时不会阻塞主线程。
  • 回调------可以注册回调以在未来完成时执行。
  • 链式处理 - future 可以链接在一起以管道异步步骤。
  • 异常处理------异常是通过回调显式处理的。
  • 线程池------默认在 ForkJoinPool 公共线程池上运行计算。

CompletableFutures 通过将线程管理与应用程序逻辑解耦来实现异步编程。然而,它们仍然会遇到诸如回调地狱之类的问题,并且使用起来并不总是直观的。

用法示例:

rust 复制代码
// Run two async tasks
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
  // long running task 
  return "Result1";
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
  // long running task
  return "Result2";  
});

// Join tasks and handle results
future1.thenCombine(future2, (res1, res2) -> {
  return res1 + " " + res2;
}).thenAccept(System.out::println);

CompletableFuture 易于使用,并且可以很好地扩展,适合中等数量的异步任务。但是,如果创建太多实例,可能会产生开销。

什么是虚拟线程?

Java 14 中引入了虚拟线程作为异步编程的替代方法。关键思想是,我们可以切换由 Java 运行时自动映射到真实线程的虚拟线程,而不是显式管理线程池。

虚拟线程的主要特点:

  • 轻量级------与操作系统线程相比,内存和资源开销较低。
  • 托管阻塞------阻塞操作不会阻塞操作系统线程,从而将它们释放以执行其他任务。
  • 结构化并发------虚拟线程从父线程继承上下文。
  • 异步------不需要基于回调的代码。可以使用同步代码风格。
  • 优化的扩展------可以有效地启动数千个虚拟线程。

个例子:

typescript 复制代码
public class Main {

  public static void main(String[] args) {

    VirtualThread vt = VirtualMachine.getInstance().virtualThread(
      () -> {
        // long running task 
      }
    );

    vt.start();
    // can continue executing main thread logic

  }

}

虚拟线程旨在提供更简单的线程模型,可以更好地扩展并避免诸如回调地狱之类的问题。编程模型更像是同步代码,但执行是异步的。

主要差异

可完成的 future 和虚拟线程之间的一些主要区别:

  • 风格 - CompletableFuture 具有基于回调的风格,而虚拟线程允许异步逻辑的同步编码风格。
  • 阻塞------虚拟线程上的阻塞操作不会像可完成的未来那样消耗操作系统线程。
  • 开销------虚拟线程的资源开销比可完成的 future 使用的线程/线程池低。
  • 结构化并发------虚拟线程从父线程继承上下文,而可完成的 future 没有内置的父子关系概念。
  • 链接------CompletableFuture 可以更轻松地将多个未来阶段直接链接在一起。使用虚拟线程链接逻辑需要显式代码。
  • 错误处理------虚拟线程上未处理的异常会终止线程,而可完成的 future 需要通过回调进行处理。

总结:

  • CompletableFuture 是高级的、灵活的,但会产生开销。对于编写许多小任务很有用。
  • 虚拟线程是轻量级的并提供结构化并发。更适合较少的长时间运行任务。

两者都有其优点和用例,但虚拟线程代表了 Java 平台上异步编程的演变。两者之间的选择取决于应用程序要求和首选编程风格

相关推荐
冯志浩16 天前
Harmony NEXT:如何给数据库添加自定义分词
harmonyos·掘金·金石计划
中杯可乐多加冰2 个月前
【AI落地应用实战】DAMODEL深度学习平台部署+本地调用ChatGLM-6B解决方案
人工智能·掘金·金石计划
中杯可乐多加冰2 个月前
Amazon Bedrock +Amazon Step Functions实现链式提示(Prompt Chaining)
人工智能·掘金·金石计划
阿李贝斯3 个月前
el-select海量数据渲染-分页解决方案
前端·javascript·掘金·金石计划
宇宙之一粟4 个月前
Error Flows in Go
后端·go·掘金·金石计划
雨绸缪4 个月前
如何在 Eclipse 中调试ABAP程序
后端·掘金·金石计划
中杯可乐多加冰4 个月前
解决方案:昇腾aarch64服务器安装CUDA+GCC+CMake,编译安装Pytorch,华为昇腾HPC服务器深度学习环境安装全流程
人工智能·掘金·金石计划
雨绸缪5 个月前
第 1章 BW 建模工具概念介绍
后端·数据挖掘·掘金·金石计划
宇宙之一粟5 个月前
Python Asyncio 如何工作?从零开始重新创建
后端·python·掘金·金石计划