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 并发编程中的重要工具。

相关推荐
qq_2975746718 小时前
【实战教程】SpringBoot 实现多文件批量下载并打包为 ZIP 压缩包
java·spring boot·后端
老毛肚18 小时前
MyBatis插件原理及Spring集成
java·spring·mybatis
学嵌入式的小杨同学18 小时前
【Linux 封神之路】信号编程全解析:从信号基础到 MP3 播放器实战(含核心 API 与避坑指南)
java·linux·c语言·开发语言·vscode·vim·ux
lang2015092818 小时前
JSR-340 :高性能Web开发新标准
java·前端·servlet
Re.不晚19 小时前
Java入门17——异常
java·开发语言
缘空如是19 小时前
基础工具包之JSON 工厂类
java·json·json切换
追逐梦想的张小年19 小时前
JUC编程04
java·idea
好家伙VCC19 小时前
### WebRTC技术:实时通信的革新与实现####webRTC(Web Real-TimeComm
java·前端·python·webrtc
南极星100520 小时前
蓝桥杯JAVA--启蒙之路(十)class版本 模块
java·开发语言
消失的旧时光-194320 小时前
第十三课:权限系统如何设计?——RBAC 与 Spring Security 架构
java·架构·spring security·rbac