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 平台上异步编程的演变。两者之间的选择取决于应用程序要求和首选编程风格

相关推荐
光影少年9 天前
react打包优化和配置优化都有哪些?
前端·react.js·掘金·金石计划
光影少年11 天前
Promise.all实现其中有一个接口失败其他结果正常返回,如何实现?
前端·promise·掘金·金石计划
光影少年11 天前
react16中的hooks的底层实现原理
前端·react.js·掘金·金石计划
光影少年21 天前
vite打包优化有哪些
前端·vite·掘金·金石计划
光影少年23 天前
webpack打包优化
webpack·掘金·金石计划·前端工程化
光影少年24 天前
Typescript工具类型
前端·typescript·掘金·金石计划
光影少年1 个月前
Promise状态和方法都有哪些,以及实现原理
javascript·promise·掘金·金石计划
光影少年1 个月前
next.js和nuxt与普通csr区别
nuxt.js·掘金·金石计划·next.js
光影少年1 个月前
js异步解决方案以及实现原理
前端·javascript·掘金·金石计划
光影少年1 个月前
前端上传切片优化以及实现
前端·javascript·掘金·金石计划