CompletableFuture教程

CompletableFuture 是 Java 8 引入的一个非常强大的类,用于异步编程,它支持非阻塞的异步执行、组合多个异步操作以及处理异常等。通过 CompletableFuture,你可以更方便地编写并发和异步代码,避免回调地狱。

1. 创建 CompletableFuture

CompletableFuture 可以通过多种方式创建:

使用静态方法创建
  • supplyAsync:执行一个异步任务,返回一个结果。
  • runAsync:执行一个异步任务,不返回结果。
// 1. 使用 supplyAsync 创建 CompletableFuture
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    // 模拟耗时任务
    try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
    return 42; // 返回结果
});

// 2. 使用 runAsync 创建 CompletableFuture
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
    // 执行没有返回值的异步任务
    try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }
    System.out.println("任务完成");
});

2. 获取结果

你可以使用 get()join() 方法来阻塞获取异步任务的结果:

// 获取结果,get() 是阻塞方法
try {
    Integer result = future.get(); // 阻塞直到获取结果
    System.out.println("结果是:" + result);
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}

// 或者使用 join()(类似 get,但不会抛出异常)
Integer result2 = future.join();
System.out.println("结果是:" + result2);

3. 处理异步结果

CompletableFuture 提供了多种方法来处理异步任务的结果,包括 thenApplythenAcceptthenRun 等。

  • thenApply:处理返回结果并继续异步执行。
  • thenAccept:处理返回结果并不继续后续操作。
  • thenRun:不处理返回值,只执行后续操作。
// 1. 使用 thenApply 处理异步结果并返回新的结果
CompletableFuture<Integer> transformedFuture = future.thenApply(result -> {
    return result * 2; // 将结果乘以 2
});

// 2. 使用 thenAccept 只消费结果,不返回
future.thenAccept(result -> {
    System.out.println("处理结果:" + result);
});

// 3. 使用 thenRun 只执行副作用任务
future.thenRun(() -> {
    System.out.println("任务完成后执行的操作");
});

4. 异常处理

CompletableFuture 还提供了异常处理的方法 exceptionallyhandle,当任务执行失败时,可以捕获异常并进行处理。

// 异常处理
CompletableFuture<Integer> exceptionFuture = future.exceptionally(ex -> {
    System.out.println("发生异常:" + ex.getMessage());
    return -1; // 返回一个默认值
});

handle 方法不仅能处理正常结果,还能处理异常,并返回一个结果。

CompletableFuture<Integer> handledFuture = future.handle((result, ex) -> {
    if (ex != null) {
        System.out.println("发生异常:" + ex.getMessage());
        return -1;
    }
    return result * 2;
});

5. 组合多个异步任务

CompletableFuture 可以将多个异步任务链式组合执行,包括 thenCombinethenComposeallOf 等方法。

thenCombine:组合两个独立的任务的结果
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);

CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
    return result1 + result2; // 合并两个结果
});
thenCompose:链式组合任务,适用于需要使用前一个结果来启动后一个任务的情况
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> composedFuture = future.thenCompose(result -> {
    // 将第一个结果用于下一个任务
    return CompletableFuture.supplyAsync(() -> result * 2);
});
allOf:等待多个异步任务完成
CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> 2);
CompletableFuture<Void> future3 = CompletableFuture.supplyAsync(() -> 3);

CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2, future3);
allOf.join(); // 等待所有任务完成
System.out.println("所有任务完成");
anyOf:等待任意一个异步任务完成
CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2, future3);
anyOf.join(); // 等待任意一个任务完成
System.out.println("至少有一个任务完成");

6. 取消任务

如果异步任务在执行过程中需要取消,可以调用 cancel 方法。

future.cancel(true); // true 表示中断正在执行的任务

7. 完整示例

import java.util.concurrent.*;

public class CompletableFutureExample {

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        // 异步任务1
        CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
            try { 
            Thread.sleep(1000); 
            } catch (InterruptedException e) {
             e.printStackTrace(); 
             }
            return 10;
        });

        // 异步任务2
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            try { 
            Thread.sleep(2000);
             } catch (InterruptedException e) {
              e.printStackTrace(); 
             }
            return 20;
        });

        // 结果合并
        CompletableFuture<Integer> combined = future1.thenCombine(future2, (result1, result2) -> result1 + result2);

        // 获取最终结果
        Integer result = combined.get();
        System.out.println("最终结果: " + result); // 输出 30

        // 等待所有任务完成
        CompletableFuture.allOf(future1, future2).join();
    }
}

总结

方法名称描述返回类型
supplyAsync(Supplier<T> supplier)异步执行任务并返回一个结果。CompletableFuture<T>
runAsync(Runnable runnable)异步执行任务,但没有返回值。CompletableFuture<Void>
get()获取异步任务的结果,阻塞直到任务完成。T
join()获取异步任务的结果,阻塞直到任务完成,类似 get(),但不会抛出异常。T
thenApply(Function<T, U> fn)任务完成后,处理结果并返回新结果。CompletableFuture<U>
thenAccept(Consumer<T> action)任务完成后,消费结果,不返回新结果。CompletableFuture<Void>
thenRun(Runnable action)任务完成后,执行某个副作用操作,不处理返回值。CompletableFuture<Void>
exceptionally(Function<Throwable, ? extends T> fn)异常处理,当任务抛出异常时执行给定的操作。CompletableFuture<T>
handle(BiFunction<T, Throwable, ? extends T> fn)任务完成后,无论成功或失败都会执行指定的操作。CompletableFuture<T>
thenCombine(CompletableFuture<U> other, BiFunction<T, U, V> fn)合并两个独立的异步任务的结果。CompletableFuture<V>
thenCompose(Function<T, CompletableFuture<U>> fn)链式组合任务,前一个任务的结果会作为输入传给下一个任务。CompletableFuture<U>
allOf(CompletableFuture<?>... futures)等待多个异步任务完成,返回 VoidCompletableFuture<Void>
anyOf(CompletableFuture<?>... futures)等待任意一个异步任务完成,返回该任务的结果。CompletableFuture<Object>
cancel(boolean mayInterruptIfRunning)取消异步任务。boolean
complete(T value)手动完成 CompletableFuture,即设置任务的完成结果。void
isCompletedExceptionally()判断 CompletableFuture 是否由于异常完成。boolean
isDone()判断任务是否完成,无论是正常完成还是异常完成。boolean
getNow(T valueIfAbsent)获取结果,如果尚未完成,则返回默认值。T
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值