首页 > 编程语言 >java8 新特性(二)CompletableFuture类

java8 新特性(二)CompletableFuture类

时间:2023-12-27 23:33:43浏览次数:33  
标签:异步 处理 编程 特性 任务 线程 CompletableFuture java8

CompletableFuture 是Java 8中引入的一个新特性,它表示异步计算的结果。通过使用 CompletableFuture,可以方便地处理异步计算,并能够在计算完成后执行回调函数。

CompletableFuture是Java 8中引入的一个功能强大的类,它实现了Future接口,并在此基础上进行了丰富的扩展,以简化异步编程的复杂性。以下是有关CompletableFuture的一些关键点:

  1. 异步编程:CompletableFuture被设计用于异步编程。这意味着在主线程之外创建一个独立的线程,并在上面运行一个非阻塞的任务。一旦任务完成,CompletableFuture会通知主线程任务的进展、成功或失败。
  2. 链式与组合处理:与Future相比,CompletableFuture的一个主要优势是它能够轻松地链式或组合多个任务。这允许您以声明式方式组织不同任务的运行顺序、规则以及方式。这在处理复杂的异步工作流时特别有用,因为它减少了回调地狱(callback hell)和错误处理的复杂性。
  3. 函数式编程能力:CompletableFuture提供了函数式编程的能力,允许您通过回调的方式处理计算结果。这增加了代码的可读性和可维护性,同时简化了错误处理。
  4. 转换和组合方法:CompletableFuture类提供了一系列方法,允许您转换和组合多个CompletableFuture对象。例如,您可以使用thenApply()、thenCompose()、thenCombine()等方法对异步操作的结果进行转换和组合。
  5. 异常处理:CompletableFuture提供了一种机制来处理和传播异常。如果异步操作失败,您可以使用exceptionally()或handle()方法来处理异常。这使得异常处理更为直观和一致。

总的来说,CompletableFuture是Java 8中引入的一个非常有用的工具,用于简化异步编程的复杂性。它提供了丰富的功能来链式、组合和处理多个异步任务,同时支持函数式编程和异常处理。

尽管CompletableFuture在异步编程中提供了许多优势,但它也存在一些潜在的缺点:

  1. 性能开销:CompletableFuture的设计和功能实现需要一定的性能开销。与传统的同步编程相比,异步编程通常需要更多的计算和资源来处理任务之间的协调和通信。
  2. 代码复杂度增加:使用CompletableFuture进行异步编程可能会增加代码的复杂度。由于异步任务之间的依赖关系和组合方式变得更加复杂,因此需要仔细设计和组织代码以确保其正确性和可维护性。
  3. 异常处理挑战:尽管CompletableFuture提供了一些方法来处理异常,但在复杂的异步操作中跟踪和处理异常仍然可能是一个挑战。处理异步操作中的异常可能比同步编程更加复杂和困难。
  4. 线程管理:使用CompletableFuture进行异步编程需要管理线程。由于每个异步任务可能在不同的线程上运行,因此需要谨慎地处理线程安全和同步问题。
  5. 非阻塞性操作的不确定性:由于CompletableFuture基于异步编程,某些操作(例如计时器或轮询)的结果可能会因为其他线程的操作而变得不确定。这可能导致难以预测和控制程序的执行流程。

请注意,这些缺点并不意味着CompletableFuture不是一个有用的工具,但在使用它时需要权衡其优点和潜在的缺点,并根据具体的应用场景和需求做出决策。


如何使用

CompletableFuture 是 Java 8 引入的一个强大的类,用于简化异步编程。以下是使用 CompletableFuture 的基本步骤:

  1. 创建 CompletableFuture 实例
java复制代码
 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {  
 
     // 执行长时间运行的任务  
 
     return "任务结果";  
 
 });
  1. 链式处理:可以使用 thenApplythenAcceptthenCompose 等方法来链式处理异步任务的结果。

例如,对异步任务的结果进行某种转换:

java复制代码
 future.thenApply(result -> {  
 
     // 对 result 进行转换  
 
     return result.toUpperCase();  
 
 }).thenAccept(System.out::println);
  1. 异常处理:如果异步任务抛出异常,可以使用 exceptionallyhandle 等方法来处理。

例如,捕获并打印异常:

java复制代码
 future.exceptionally(ex -> {  
 
     System.err.println("出现异常: " + ex.getMessage());  
 
     return null; // 或其他默认值  
 
 }).thenAccept(System.out::println);
  1. 等待结果:如果你需要等待异步任务完成并获取结果,可以使用 join 方法。这会阻塞当前线程,直到异步任务完成。

例如:

java复制代码
 try {  
 
     String result = future.join(); // 阻塞,直到任务完成并返回结果  
 
     System.out.println("任务结果: " + result);  
 
 } catch (Exception e) {  
 
     e.printStackTrace();  
 
 }
  1. 组合多个 CompletableFuture:可以使用 thenCombinethenAcceptBoth 等方法来组合多个 CompletableFuture。
  2. 取消任务:可以使用 cancel 方法来取消未完成的异步任务。如果任务已经完成,则取消操作不会产生任何影响。
  3. 超时:可以使用 timeout 方法为异步任务设置一个超时时间。如果任务在超时时间内没有完成,会抛出 TimeoutException。
  4. 依赖性:通过使用 thenRun 和 runAfterBoth 等方法,可以设置一个任务在另一个任务完成之后运行。这对于创建有依赖关系的异步任务非常有用。
  5. 序列化:如果多个线程可能同时修改一个 CompletableFuture,可以使用 allOf 和 anyOf 方法来序列化这些操作。这些方法返回的 CompletableFuture 会确保多个线程不会同时修改它。
  6. 线程池:通过 CompletableFuture.supplyAsync 的重载版本,你可以指定一个自定义的线程池来执行异步任务。例如,使用固定大小的线程池:
java复制代码
 CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {  
 
     // 长时间运行的任务...  
 
 }, Executors.newFixedThreadPool(10)); // 使用大小为10的线程池来执行任务
  1. 使用 orTimeout 和 orApply 替代 join:如果你不希望阻塞当前线程,而是希望在超时或某个条件满足时执行特定的操作,可以使用 orTimeout 或 orApply 方法替代 join。这些方法不会阻塞当前线程,而是在给定的超时时间或条件满足时执行指定的操作。

标签:异步,处理,编程,特性,任务,线程,CompletableFuture,java8
From: https://blog.51cto.com/u_11924918/9004921

相关文章

  • 使用java8 将pdf转为tif文件并设定图片格式
    在工作中,遇到一个需要将pdf转为tif并将图片大小限制到30kb以内的需求。在网上看了一圈,也因为依赖版本等等踩了一些坑,为此记录下来学习的过程。`importcom.github.jaiimageio.impl.plugins.tiff.TIFFImageWriterSpi;importcom.github.jaiimageio.plugins.tiff.BaselineTIFFTagS......
  • java 8 的新特性(三)
    java8新的日期时间APIJava8引入了一个新的日期时间API,也称为java.timeAPI,以替代旧的java.util.Date和java.util.Calendar类。这个新API提供了更清晰、更强大和更易于使用的日期和时间功能。Java8的日期时间API包括以下部分:日期和时间类型:包括LocalDate(日期),LocalTime(时间),LocalDa......
  • 特性语法-补充
    NSUserDefaults以K-V键值对的形式存储到本地文件(plist),使用时非常方便(小量数据使用)使用存储NSUserDefaults*user=[NSUserDefaultsstandardUserDefaults];[usersetObject:@"jack"forKey:@"name"];[usersetInteger:18forKey:@"age"];[usersynchronize];取出NSUserD......
  • IGP协议高级特性
    一、快速收敛  1.i-SPF增量SPF算法:    初始收敛时,使用Full-SPF算法计算去往拓扑构建最短路径树    当最短路径树出现变更,只对变更的部分进行i-SPF计算,未出现变更的部分不需要         重新计算,减少设备资源的消耗,提高收敛速度  ......
  • 深入了解 Spring Boot 核心特性、注解和 Bean 作用域
    SpringBoot是什么?SpringBoot是基于SpringFramework构建应用程序的框架,SpringFramework是一个广泛使用的用于构建基于Java的企业应用程序的开源框架。SpringBoot旨在使创建独立的、生产级别的Spring应用程序变得容易,您可以"只是运行"这些应用程序。术语SpringCor......
  • C#版本与.NET版本对应关系以及各版本的特性
    C#版本与.NET版本对应关系以及各版本的特性 C#版本.NET版本发布日期特性C#1.0.NETFramework1.02002-02-13委托、事件C#1.1.NETFramework1.12003-04-24APM(异步编程模型)C#2.0.NETFramework2.02005-11-07泛型、匿名方法、迭代器、可空类型C#......
  • 18 事务必须遵循ACID这4个特性
    事务必须遵循ACID这4个特性。分别代表原子性、一致性、隔离性、持久性。原子性就代表,事务的执行和回退是一个整体,事务中包含的sql要么全部执行,要么全部回退。一致性就是,事务执行前后,数据库都是处于一致性状态中。隔离性就是,事务在提交之前,对于其它事务都是不可见的。直到提交时。持......
  • RocketMQ的特性介绍和常用的业务场景
    RocketMQ(ApacheRocketMQ)是一个开源的分布式消息中间件系统,最初由阿里巴巴开发并捐赠给Apache软件基金会。它是一个可靠、可扩展、高吞吐量、低延迟的分布式消息系统,适用于大规模分布式系统中的消息通信。以下是RocketMQ的一些主要特性和常用场景:特性介绍:分布式架构:RocketMQ采用了......
  • Java8之函数式接口@FunctionalInterface和lambada表达式
    跟着孙哥学Spring,b站:https://www.bilibili.com/video/BV185411477k/?spm_id_from=333.337.search-card.all.click在Java中,函数式接口和Lambda表达式是一种常见的编程模式,主要用于简化代码和提高代码的可读性。函数式接口(FunctionalInterface)函数式接口是Java8中引入的一个......
  • java8排序
    升序List<Transaction>transactions=Arrays.asList(newTransaction(brian,2011,300),newTransaction(raoul,2012,1000),newTransaction(raoul,2011,400),newTransaction(mario,2012,......