Java CompletableFuture 使用详解

Java CompletableFuture 使用详解

CompletableFuture 是 Java 8 引入的异步编程工具,它实现了 FutureCompletionStage 接口,提供了强大的异步编程能力。

1. 基础创建方式

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

public class CompletableFutureBasics {
    
    // 1. 直接创建已完成的 Future
    public static void completedFutureExample() {
        CompletableFuture<String> future = CompletableFuture.completedFuture("Hello");
        try {
            System.out.println(future.get()); // 输出: Hello
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 2. 使用 runAsync 执行无返回值的异步任务
    public static void runAsyncExample() {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("异步任务执行中...");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("异步任务完成");
        });
        
        future.join(); // 等待任务完成
    }
    
    // 3. 使用 supplyAsync 执行有返回值的异步任务
    public static void supplyAsyncExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "异步任务结果";
        });
        
        try {
            String result = future.get(); // 阻塞获取结果
            System.out.println("结果: " + result);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 回调处理(链式操作)

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CallbackExample {
    
    public static void thenApplyExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello";
        });
        
        // thenApply: 转换结果
        CompletableFuture<String> greetingFuture = future.thenApply(s -> s + " World");
        
        // thenAccept: 消费结果,无返回值
        greetingFuture.thenAccept(s -> System.out.println("结果: " + s));
        
        // thenRun: 任务完成后执行,不关心结果
        greetingFuture.thenRun(() -> System.out.println("任务完成"));
        
        greetingFuture.join();
    }
    
    public static void thenComposeExample() {
        // thenCompose: 组合两个 Future,第二个依赖于第一个的结果
        CompletableFuture<String> future = getUserInfo("123")
            .thenCompose(user -> getOrderInfo(user));
        
        future.thenAccept(System.out::println).join();
    }
    
    private static CompletableFuture<String> getUserInfo(String userId) {
        return CompletableFuture.supplyAsync(() -> "用户" + userId);
    }
    
    private static CompletableFuture<String> getOrderInfo(String user) {
        return CompletableFuture.supplyAsync(() -> user + "的订单信息");
    }
}

3. 组合多个 Future

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class CombineExample {
    
    public static void thenCombineExample() {
        // thenCombine: 组合两个独立的 Future
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello";
        });
        
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "World";
        });
        
        // 组合两个结果
        CompletableFuture<String> combined = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
        
        System.out.println(combined.join()); // 输出: Hello World
    }
    
    public static void allOfExample() {
        // allOf: 等待所有 Future 完成
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "结果1");
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "结果2");
        CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "结果3");
        
        CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);
        
        allFutures.thenRun(() -> {
            try {
                System.out.println("所有任务完成: " + future1.get() + ", " + future2.get() + ", " + future3.get());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).join();
    }
    
    public static void anyOfExample() {
        // anyOf: 任意一个 Future 完成即可
        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "结果1";
        });
        
        CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "结果2";
        });
        
        CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2);
        
        System.out.println("最先完成的结果: " + anyFuture.join()); // 输出: 结果2
    }
}

4. 异常处理

java 复制代码
import java.util.concurrent.CompletableFuture;

public class ExceptionHandlingExample {
    
    public static void exceptionallyExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            if (true) {
                throw new RuntimeException("发生异常");
            }
            return "正常结果";
        });
        
        // exceptionally: 发生异常时提供默认值
        CompletableFuture<String> safeFuture = future.exceptionally(ex -> {
            System.out.println("捕获异常: " + ex.getMessage());
            return "默认值";
        });
        
        System.out.println(safeFuture.join()); // 输出: 默认值
    }
    
    public static void handleExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 这里可能会成功,也可能会失败
            return "正常结果";
            // throw new RuntimeException("发生异常");
        });
        
        // handle: 无论成功还是失败都会执行
        CompletableFuture<String> handledFuture = future.handle((result, ex) -> {
            if (ex != null) {
                return "异常处理结果";
            }
            return "处理后的: " + result;
        });
        
        System.out.println(handledFuture.join());
    }
    
    public static void whenCompleteExample() {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // throw new RuntimeException("测试异常");
            return "成功结果";
        });
        
        // whenComplete: 任务完成后执行,可获取结果和异常
        future.whenComplete((result, ex) -> {
            if (ex != null) {
                System.out.println("任务异常: " + ex.getMessage());
            } else {
                System.out.println("任务成功: " + result);
            }
        }).join();
    }
}

5. 超时处理(Java 9+)

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class TimeoutExample {
    
    public static void orTimeoutExample() {
        // orTimeout: Java 9+ 的超时方法
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "慢任务结果";
        }).orTimeout(1, TimeUnit.SECONDS) // 设置1秒超时
          .exceptionally(ex -> {
              if (ex instanceof TimeoutException) {
                  return "超时,返回默认值";
              }
              return "其他异常";
          });
        
        System.out.println(future.join()); // 输出: 超时,返回默认值
    }
    
    public static void completeOnTimeoutExample() {
        // completeOnTimeout: 超时时完成并返回默认值
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "慢任务结果";
        }).completeOnTimeout("超时默认值", 1, TimeUnit.SECONDS);
        
        System.out.println(future.join()); // 输出: 超时默认值
    }
}

6. 实际应用示例

java 复制代码
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;

public class PracticalExample {
    
    // 自定义线程池
    private static final ExecutorService executor = Executors.newFixedThreadPool(10);
    
    public static void parallelTasksExample() {
        List<String> ids = List.of("1", "2", "3", "4", "5");
        
        // 并行查询多个ID的信息
        List<CompletableFuture<String>> futures = ids.stream()
            .map(id -> CompletableFuture.supplyAsync(() -> queryDatabase(id), executor))
            .collect(Collectors.toList());
        
        // 等待所有查询完成
        List<String> results = futures.stream()
            .map(CompletableFuture::join)
            .collect(Collectors.toList());
        
        System.out.println("查询结果: " + results);
    }
    
    private static String queryDatabase(String id) {
        try {
            TimeUnit.MILLISECONDS.sleep(500); // 模拟数据库查询
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "数据" + id;
    }
    
    public static void pipelineExample() {
        // 构建处理流水线
        CompletableFuture<String> pipeline = CompletableFuture
            .supplyAsync(() -> "原始数据", executor)
            .thenApplyAsync(data -> data + " -> 步骤1处理", executor)
            .thenApplyAsync(data -> data + " -> 步骤2处理", executor)
            .thenApplyAsync(data -> data + " -> 步骤3处理", executor)
            .thenApplyAsync(data -> data + " -> 完成", executor);
        
        System.out.println("流水线结果: " + pipeline.join());
    }
    
    public static void shutdown() {
        executor.shutdown();
    }
    
    public static void main(String[] args) {
        try {
            parallelTasksExample();
            pipelineExample();
        } finally {
            shutdown();
        }
    }
}

7. 最佳实践

  1. 使用自定义线程池:避免使用默认的 ForkJoinPool,防止影响其他任务
  2. 合理处理异常:使用 exceptionally、handle 等方法处理异常
  3. 避免阻塞:尽量使用 thenApply、thenAccept 等非阻塞方法
  4. 资源清理:及时关闭自定义的 ExecutorService
  5. 避免嵌套过深:保持链式调用的可读性

8. 主要方法总结

方法 描述
supplyAsync() 异步执行有返回值的任务
runAsync() 异步执行无返回值的任务
thenApply() 对结果进行转换
thenAccept() 消费结果,无返回值
thenRun() 任务完成后执行,不关心结果
thenCompose() 组合两个有依赖关系的 Future
thenCombine() 组合两个独立的 Future
allOf() 等待所有 Future 完成
anyOf() 任意一个 Future 完成即可
exceptionally() 异常处理
handle() 处理结果和异常
whenComplete() 完成后执行回调

CompletableFuture 使得异步编程变得更加简洁和强大,是 Java 并发编程中的重要工具。

相关推荐
jiayong232 小时前
MINA框架面试题 - 实战篇
java·io·mina
数智工坊2 小时前
【操作系统-处理器调度】
java·linux·服务器·windows·ubuntu
Coder_Boy_2 小时前
基于SpringAI的在线考试系统-考试管理功能布局+交互优化方案
java·数据库·人工智能·spring boot·交互·ddd·tdd
Tao____2 小时前
可以本地部署的物联网平台
java·开发语言·物联网·mqtt·低代码
码界奇点2 小时前
基于DDD与CQRS的Java企业级应用框架设计与实现
java·开发语言·c++·毕业设计·源代码管理
柏林以东_2 小时前
线程安全的数据集合
java·开发语言·安全
进阶的猿猴2 小时前
java中实现markdown转为pdf
java·pdf·markdown
sunnyday04262 小时前
Nginx与Spring Cloud Gateway QPS统计全攻略
java·spring boot·后端·nginx
海南java第二人2 小时前
Spring Boot全局异常处理终极指南:打造优雅的API错误响应体系
java·spring boot·后端