您的位置:

深入理解SpringBoot CompletableFuture

一、基础概念

CompletableFuture是Java 8提供的一个类,用于处理异步任务的计算结果。

在Spring Boot中,我们可以使用CompletableFuture来实现异步调用,在处理并发请求的场景下提高系统性能。

CompletableFuture封装了异步执行的任务,我们可以通过一系列的方法链式调用来对任务的结果进行进一步的处理。

二、入门示例

下面我们通过一个简单的示例了解CompletableFuture的基本用法。

CompletableFuture.supplyAsync(() -> "hello world")
                 .thenAccept(result -> System.out.println(result));

这段代码实现了一个简单的异步调用,并打印出"hello world"。

在这段代码中,我们首先调用CompletableFuture的静态方法supplyAsync来创建一个CompletableFuture对象,其中传入的参数是一个Supplier类型的lambda表达式,用于异步执行一个任务,并返回计算结果。

接着,我们通过thenAccept方法链式调用接收处理结果,其中传入的参数是一个Consumer类型的lambda表达式,用于对计算结果进行进一步处理。

三、使用场景

CompletableFuture可以应用于很多场景,例如:

1.并发请求

当有大量请求需要处理时,使用CompletableFuture可以并发执行多个请求,提高系统性能。

CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "hello");
CompletableFuture
    future2 = CompletableFuture.supplyAsync(() -> "world");

CompletableFuture
     result = CompletableFuture.allOf(future1, future2)
        .thenApply(v -> Stream.of(future1, future2)
                .map(CompletableFuture::join)
                .collect(Collectors.joining(" ")));

System.out.println(result.get());

    
   
  

在这段代码中,我们使用了CompletableFuture.allOf方法来并发执行两个请求,并通过thenApply方法处理两个请求的结果,最终输出结果为"hello world"。

2.异步IO

CompletableFuture还可以用于异步IO操作,例如读取文件、查询数据库等,可以有效地提高IO效率。

CompletableFuture.supplyAsync(() -> {
    try {
        return Files.readString(Paths.get("file.txt"));
    } catch (IOException e) {
        return null;
    }
}).thenAccept(result -> System.out.println(result));

在这段代码中,我们使用CompletableFuture来读取一个文件的内容,并异步地返回结果,最终通过thenAccept方法输出文件内容。

3.批处理

CompletableFuture还可以用于批处理操作,例如对多个数据进行计算、加工等。

List dataList = Arrays.asList("hello", "world", "java");

List
   
    > futures = dataList.stream()
        .map(data -> CompletableFuture.supplyAsync(() -> data.toUpperCase()))
        .collect(Collectors.toList());

CompletableFuture
      allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));

CompletableFuture
      
       
        > results = allFutures.thenApply(v -> futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList())); results.thenAccept(list -> System.out.println(list));
       
      
     
    
   
  

在这段代码中,我们使用CompletableFuture对多个数据进行批处理,并返回一组结果。

四、异常处理

在使用CompletableFuture时,我们也需要考虑到异常处理的问题。

对于异步执行的任务,如果出现异常,我们可以通过异常处理方法进行处理。

CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("error");
}).exceptionally(ex -> "error handled")
  .thenAccept(result -> System.out.println(result));

在这段代码中,我们通过异常处理方法exceptionally来捕获并处理异常,输出结果为"error handled"。

当然,我们也可以通过其他的方法来进行异常处理,例如handle方法、whenComplete方法等。

五、完整示例

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.io.IOException;

public class CompletableFutureDemo {

    public static void main(String[] args) throws Exception {
        // 示例1:简单异步调用
        CompletableFuture.supplyAsync(() -> "hello world")
                         .thenAccept(result -> System.out.println(result));

        // 示例2:并发请求
        CompletableFuture future1 = CompletableFuture.supplyAsync(() -> "hello");
        CompletableFuture
    future2 = CompletableFuture.supplyAsync(() -> "world");

        CompletableFuture
     result = CompletableFuture.allOf(future1, future2)
                .thenApply(v -> Stream.of(future1, future2)
                        .map(CompletableFuture::join)
                        .collect(Collectors.joining(" ")));

        System.out.println(result.get());

        // 示例3:异步IO操作
        CompletableFuture.supplyAsync(() -> {
            try {
                return Files.readString(Paths.get("file.txt"));
            } catch (IOException e) {
                return null;
            }
        }).thenAccept(result -> System.out.println(result));

        // 示例4:批处理操作
        List
      dataList = Arrays.asList("hello", "world", "java");

        List
      
       
        > futures = dataList.stream() .map(data -> CompletableFuture.supplyAsync(() -> data.toUpperCase())) .collect(Collectors.toList()); CompletableFuture
        
         allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])); CompletableFuture
         
          
           > results = allFutures.thenApply(v -> futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList())); results.thenAccept(list -> System.out.println(list)); // 示例5:异常处理 CompletableFuture.supplyAsync(() -> { throw new RuntimeException("error"); }).exceptionally(ex -> "error handled") .thenAccept(result -> System.out.println(result)); } }