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

相关推荐
中杯可乐多加冰25 天前
【AI落地应用实战】Amazon Bedrock Converse API + Amazon Titan构建一个RAG应用(Retrieval-Augmente
人工智能·掘金·金石计划
边中之城1 个月前
如何从0到1开发自己的npm包
掘金·金石计划
中杯可乐多加冰1 个月前
Text to image论文精读PDF-GAN:文本生成图像新度量指标SSD Semantic Similarity Distance
人工智能·掘金·金石计划
Sword991 个月前
Rust 所有权理解与运用
前端·rust·掘金·金石计划
冯志浩1 个月前
Harmony Next - 图形绘制
harmonyos·掘金·金石计划
中杯可乐多加冰2 个月前
【AI落地应用实战】HivisionIDPhotos AI证件照制作实践指南
人工智能·掘金·金石计划
冯志浩2 个月前
Harmony Next - 多线程技术 TaskPool
harmonyos·掘金·金石计划
宇宙之一粟2 个月前
设计快速并发哈希表
后端·rust·掘金·金石计划
宇宙之一粟2 个月前
【译】Go 迭代器的乐趣
后端·go·掘金·金石计划
雨绸缪2 个月前
ABAP 的 “小技巧 ”和 “陷阱 ”以及新语法
后端·代码规范·掘金·金石计划