如何使用 Java 的 `CompletableFuture` 类来进行异步编程,同时处理成功和失败的情况。代码分为以下几个部分:
1. 工具列表创建
List<String> tools = Arrays.asList("q,w,e,r".split(","));
这一部分创建了一个包含字符串元素的列表,这些字符串将会作为异步任务的输入数据。
2. 创建 CompletableFuture 链
List<CompletableFuture<String>> futures = tools.stream()
.map(item -> CompletableFuture.completedFuture(item).thenApplyAsync(data -> {
// 业务处理
String processedData = processData(data);
System.out.println("Processed data: " + processedData);
return processedData;
}).exceptionally(ex -> {
// 异常处理
handleException(ex);
return null;
})
).collect(Collectors.toList());
在这部分,使用流式编程对工具列表中的每个元素创建了一个 `CompletableFuture`。对于每个元素,首先使用 `CompletableFuture.completedFuture` 方法将其转换为已完成的 `CompletableFuture`。然后,通过 `thenApplyAsync` 方法,在异步任务完成后对数据进行处理(通过调用 `processData` 方法)。如果任务成功,会返回处理后的数据;如果任务失败(抛出异常),会进入 `exceptionally` 块,并调用 `handleException` 方法进行异常处理。
3. 等待所有 CompletableFuture 完成
CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
allOf.join();
在这一步,使用 `CompletableFuture.allOf` 方法将所有的 `CompletableFuture` 对象合并成一个新的 `CompletableFuture`,这个新的 `CompletableFuture` 会在所有子任务都完成后完成。`join` 方法等待所有任务完成。
4.数据处理和异常处理方法
private static String processData(String data) {
// 模拟业务处理
if (data.equals("e")) {
throw new RuntimeException("自定义错误");
}
return data.toUpperCase();
}
private static void handleException(Throwable ex) {
// 模拟异常处理,打印错误信息
System.err.println("Exception occurred: " + ex.getMessage());
throw new RuntimeException(ex.getMessage());
}
这两个方法分别模拟了业务数据处理和异常处理。`processData` 方法将输入的字符串转换为大写字母,如果输入是 "e",则会抛出一个模拟异常。`handleException` 方法简单地打印异常信息并再次抛出异常。
这个代码片段演示了如何使用 CompletableFuture 来创建异步任务,并在任务处理成功或失败时进行相应的处理。在代码中处理了异常,尽管在 exceptionally 块中抛出了新的异常,但实际上这样做可能会导致异常不被完全捕获,这可能不是你想要的行为。通常情况下,最好是在 exceptionally 块中进行日志记录或其他适当的处理,而不是再次抛出异常。
另外,要注意在 handleException 方法中抛出了一个新的 RuntimeException,这可能会影响异常处理流程。通常建议在异常处理方法中避免再次抛出异常,而是根据具体情况决定如何处理异常。