寒假打卡06_1月18日

Java Future 和 CompletableFuture——异步编程的高级用法

在多线程编程中,异步操作是提高程序性能和响应速度的重要手段。Java 提供了 FutureCompletableFuture 类来支持异步编程。Future 是一种表示异步计算结果的机制,而 CompletableFuture 则是对 Future 的增强,提供了更加灵活和强大的功能。

Future

Future 接口表示一个异步计算的结果。它提供了检查计算是否完成、等待计算完成以及获取计算结果的方法。Future 通常由 ExecutorService 提交任务时返回。

使用场景

  • 提交异步任务并获取其结果
  • 实现并行计算

示例代码

下面是一个使用 Future 的示例,展示了如何提交异步任务并获取其结果:

import java.util.concurrent.*;

public class FutureDemo {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();

        Future<Integer> future = executor.submit(() -> {
            System.out.println("Task is running...");
            Thread.sleep(2000); // Simulate long-running task
            return 42;
        });

        try {
            System.out.println("Main thread is doing other work...");
            Integer result = future.get(); // Wait for the task to complete and get the result
            System.out.println("Task result: " + result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}

在上述代码中,主线程提交了一个异步任务,并在任务完成后获取其结果。future.get() 方法会阻塞主线程,直到任务完成并返回结果。

CompletableFuture

CompletableFutureFuture 的增强版,它提供了更加灵活和强大的异步编程功能。CompletableFuture 支持链式调用、组合多个异步任务以及处理异步任务的异常等。

使用场景

  • 实现复杂的异步任务链
  • 组合多个异步任务
  • 处理异步任务的异常

示例代码

下面是一个使用 CompletableFuture 的示例,展示了如何创建和组合异步任务:

import java.util.concurrent.*;

public class CompletableFutureDemo {
    public static void main(String[] args) {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("Task 1 is running...");
            try {
                Thread.sleep(2000); // Simulate long-running task
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 42;
        });

        CompletableFuture<Integer> future2 = future.thenApply(result -> {
            System.out.println("Task 2 is running...");
            return result * 2;
        });

        CompletableFuture<Void> future3 = future2.thenAccept(result -> {
            System.out.println("Task 3 is running...");
            System.out.println("Final result: " + result);
        });

        future3.join(); // Wait for all tasks to complete
    }
}

在上述代码中,我们创建了三个异步任务,并通过链式调用依次执行。CompletableFuture.supplyAsync 方法用于创建异步任务,thenApply 方法用于在第一个任务完成后执行第二个任务,thenAccept 方法用于在第二个任务完成后处理最终结果。

组合多个异步任务

CompletableFuture 提供了多种方法来组合多个异步任务,例如 thenCombinethenComposeallOf 等。

thenCombine

thenCombine 方法用于组合两个并发运行的异步任务,并在它们都完成后处理结果:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
    System.out.println("Task 1 is running...");
    return 42;
});

CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
    System.out.println("Task 2 is running...");
    return 24;
});

CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
    System.out.println("Combining results...");
    return result1 + result2;
});

System.out.println("Combined result: " + combinedFuture.join());

在上述代码中,两个异步任务并发运行,并在它们都完成后将结果相加。

thenCompose

thenCompose 方法用于将一个异步任务的结果作为另一个异步任务的输入:

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
    System.out.println("Task 1 is running...");
    return 42;
});

CompletableFuture<String> composedFuture = future1.thenCompose(result -> {
    return CompletableFuture.supplyAsync(() -> {
        System.out.println("Task 2 is running...");
        return "Result: " + result;
    });
});

System.out.println(composedFuture.join());

在上述代码中,第一个异步任务的结果作为第二个异步任务的输入,最终返回组合后的结果。

allOf

allOf 方法用于等待多个异步任务全部完成后再继续执行:

CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
    System.out.println("Task 1 is running...");
});

CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
    System.out.println("Task 2 is running...");
});

CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2);

allOfFuture.join();
System.out.println("All tasks have completed.");

在上述代码中,我们使用 allOf 方法等待所有异步任务完成后再继续执行主线程。

异常处理

CompletableFuture 提供了多种方法来处理异步任务中的异常,例如 exceptionallyhandlewhenComplete 等。

exceptionally

exceptionally 方法用于在异步任务抛出异常时提供默认值:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("Task failed");
}).exceptionally(ex -> {
    System.out.println("Exception: " + ex.getMessage());
    return 0;
});

System.out.println("Result: " + future.join());

handle

handle 方法用于在异步任务完成后处理结果或异常:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("Task failed");
}).handle((result, ex) -> {
    if (ex != null) {
        System.out.println("Exception: " + ex.getMessage());
        return 0;
    } else {
        return result;
    }
});

System.out.println("Result: " + future.join());

whenComplete

whenComplete 方法用于在异步任务完成后执行一些操作,无论任务是否成功:

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("Task failed");
}).whenComplete((result, ex) -> {
    if (ex != null) {
        System.out.println("Exception: " + ex.getMessage());
    } else {
        System.out.println("Result: " + result);
    }
});

future.join();

总结

FutureCompletableFuture 是 Java 提供的强大异步编程工具。Future 表示一个异步计算的结果,而 CompletableFuture 则提供了更加灵活和强大的功能,包括链式调用、组合多个异步任务以及处理异步任务的异常等。通过合理使用这些工具,我们可以编写出更加高效和健壮的异步程序。

希望通过本篇文章,大家对 Java 异步编程有了更深入的了解。在接下来的文章中,我们将继续探讨更多关于 Java 多线程的知识点,敬请期待!

posted @ 2025-01-18 09:08  aallofitisst  阅读(20)  评论(0)    收藏  举报