寒假打卡06_1月18日
Java Future 和 CompletableFuture——异步编程的高级用法
在多线程编程中,异步操作是提高程序性能和响应速度的重要手段。Java 提供了 Future
和 CompletableFuture
类来支持异步编程。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
CompletableFuture
是 Future
的增强版,它提供了更加灵活和强大的异步编程功能。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
提供了多种方法来组合多个异步任务,例如 thenCombine
、thenCompose
和 allOf
等。
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
提供了多种方法来处理异步任务中的异常,例如 exceptionally
、handle
和 whenComplete
等。
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();
总结
Future
和 CompletableFuture
是 Java 提供的强大异步编程工具。Future
表示一个异步计算的结果,而 CompletableFuture
则提供了更加灵活和强大的功能,包括链式调用、组合多个异步任务以及处理异步任务的异常等。通过合理使用这些工具,我们可以编写出更加高效和健壮的异步程序。
希望通过本篇文章,大家对 Java 异步编程有了更深入的了解。在接下来的文章中,我们将继续探讨更多关于 Java 多线程的知识点,敬请期待!