基本的异步调用
该函数演示了如何使用CompletableFuture进行基本的异步调用:
- 创建CompletableFuture,通过supplyAsync方法异步执行任务,任务包括打印当前线程名称、模拟耗时操作(睡眠2秒)并返回结果。
- 主线程继续执行,不会因异步任务阻塞,打印“Main thread continues…”。
- 通过future.get()等待异步任务完成并获取结果,最后打印结果。
public void test() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("Executing task in thread: " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Result of the computation";
});
// 这里主线程不会阻塞,可以继续执行其他任务
System.out.println("Main thread continues...");
// 等待结果完成并获取结果
String result = future.get();
System.out.println("Result: " + result);
}
运行结果:
Main thread continues...
Executing task in thread: ForkJoinPool.commonPool-worker-1
Result: Result of the computation
配合自定义线程池使用
该方法使用 CompletableFuture 和自定义线程池异步执行任务,使主线程能够继续执行其他操作。主要步骤如下:
- 创建固定大小的线程池。
- 使用线程池创建 CompletableFuture 并异步执行任务,打印执行任务的线程名称,并模拟任务执行时间。
- 主线程继续执行其他任务。
- 等待任务完成并获取结果,打印结果。
- 关闭线程池并等待所有任务完成,处理可能的中断情况。
public void test2() throws ExecutionException, InterruptedException {
// 创建一个固定大小的线程池
ExecutorService executor = Executors.newFixedThreadPool(5);
// 使用自定义线程池创建CompletableFuture
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 打印当前执行任务的线程名称
System.out.println("Executing task in thread: " + Thread.currentThread().getName());
try {
// 模拟任务执行时间
Thread.sleep(2000);
} catch (InterruptedException e) {
// 重新设置中断状态,以便后续可以检测到中断
Thread.currentThread().interrupt();
}
// 返回任务执行结果
return "Result of the computation";
}, executor);
// 这里主线程不会阻塞,可以继续执行其他任务
System.out.println("Main thread continues...");
// 等待结果完成并获取结果
try {
String result = future.get();
// 打印任务结果
System.out.println("Result: " + result);
} catch (InterruptedException | ExecutionException e) {
// 处理异常
e.printStackTrace();
}
// 关闭线程池,不再接受新任务
executor.shutdown();
// 等待线程池中所有任务完成
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
// 如果在指定时间内未完成,则强制关闭所有活动任务
executor.shutdownNow();
}
} catch (InterruptedException e) {
// 如果等待过程中被中断,则强制关闭所有活动任务
executor.shutdownNow();
// 重新设置中断状态
Thread.currentThread().interrupt();
}
}
输出:
Main thread continues...
Executing task in thread: pool-1-thread-1
Result: Result of the computation
链式调用示例
该函数演示了CompletableFuture的链式调用:
- 使用supplyAsync异步执行第一步,并打印当前线程名,返回结果"Step 1 result"。
- 通过thenApply方法,依次执行第二步和第三步,每步接收上一步的结果,在新线程中执行并修改结果字符串,最终获取并打印最终结果。
public void chainExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
System.out.println("Step 1: " + Thread.currentThread().getName());
return "Step 1 result";
}).thenApply(result -> {
System.out.println("Step 2: " + Thread.currentThread().getName());
return result + " -> Step 2 result";
}).thenApply(result -> {
System.out.println("Step 3: " + Thread.currentThread().getName());
return result + " -> Step 3 result";
});
String finalResult = future.get();
System.out.println("Final Result: " + finalResult);
}
输出:
Step 1: ForkJoinPool.commonPool-worker-1
Step 2: main
Step 3: main
Final Result: Step 1 result -> Step 2 result -> Step 3 result
异常处理示例
本方法演示了如何在CompletableFuture中处理异常。
public void exceptionHandlingExample() {
// 创建一个CompletableFuture,异步执行一个任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 打印当前执行任务的线程名称
System.out.println("Executing task in thread: " + Thread.currentThread().getName());
// 模拟异常发生,用于测试异常处理机制
if (true) {
throw new RuntimeException("Something went wrong!");
}
// 正常情况下返回任务结果
return "Result of the computation";
})
// 设置异常处理器
.exceptionally(ex -> {
// 打印异常信息
System.out.println("Exception occurred: " + ex.getMessage());
// 返回默认结果
return "Default result";
});
// 处理CompletableFuture的结果
future.thenAccept(result -> System.out.println("Result: " + result));
}
输出:
Executing task in thread: ForkJoinPool.commonPool-worker-1
Exception occurred: java.lang.RuntimeException: Something went wrong!
Result: Default result
组合多个异步任务示例
public void combineExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
System.out.println("Task 1: " + Thread.currentThread().getName());
return "Result 1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
System.out.println("Task 2: " + Thread.currentThread().getName());
return "Result 2";
});
CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> {
return result1 + " + " + result2;
});
String finalResult = combinedFuture.get();
System.out.println("Combined Result: " + finalResult);
}
输出:
Task 1: ForkJoinPool.commonPool-worker-1
Task 2: ForkJoinPool.commonPool-worker-1
Combined Result: Result 1 + Result 2
任意一个完成示例
public void anyOfExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Result 1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Result 2";
});
CompletableFuture<Object> anyOfFuture = CompletableFuture.anyOf(future1, future2);
Object result = anyOfFuture.get();
System.out.println("First completed result: " + result);
}
输出:
First completed result: Result 2
所有任务完成示例
public void allOfExample() throws ExecutionException, InterruptedException {
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Result 1";
});
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Result 2";
});
CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "Result 3";
});
CompletableFuture<Void> allOfFuture = CompletableFuture.allOf(future1, future2, future3);
allOfFuture.get(); // 等待所有任务完成
System.out.println("All tasks completed.");
System.out.println("Future 1 result: " + future1.get());
System.out.println("Future 2 result: " + future2.get());
System.out.println("Future 3 result: " + future3.get());
}
输出:
All tasks completed.
Future 1 result: Result 1
Future 2 result: Result 2
Future 3 result: Result 3
等待多个任务完成后执行新任务示例
本方法演示了如何使用CompletableFuture来协调多个异步任务的执行顺序,它首先启动三个独立的异步任务A、B、C,然后等待它们都完成后,使用它们的结果来启动一个新的异步任务D,最后从任务D获取结果并打印出来
public void dependentTasksExample() throws ExecutionException, InterruptedException {
// 标记主线程的任务1
System.out.println("main 1");
// 启动异步任务A,模拟耗时操作并返回结果
CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 任务A执行结束
System.out.println("A end");
return "Result A";
});
// 启动异步任务B,模拟耗时操作并返回结果
CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 任务B执行结束
System.out.println("B end");
return "Result B";
});
// 启动异步任务C,模拟耗时操作并返回结果
CompletableFuture<String> futureC = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 任务C执行结束
System.out.println("C end");
return "Result C";
});
// 等待所有已启动的CompletableFuture完成
CompletableFuture<Void> allOfFutures = CompletableFuture.allOf(futureA, futureB, futureC);
// 标记主线程的任务2
System.out.println("main 2");
// 创建新的CompletableFuture D,依赖于A、B、C的结果
CompletableFuture<String> futureD = allOfFutures.thenCompose(v -> {
return CompletableFuture.supplyAsync(() -> {
// 任务D执行中
System.out.println("Task D: " + Thread.currentThread().getName());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
// 任务D执行结束
System.out.println("D end");
// 返回任务D的结果,该结果是基于任务A、B、C的结果组合而成的
return "D: " + futureA.join() + ", " + futureB.join() + ", " + futureC.join();
});
});
// 标记主线程的任务3
System.out.println("main 3");
// 等待D完成并获取其结果
String finalResult = futureD.get();
// 打印最终结果
System.out.println("Final Result from D: " + finalResult);
}
输出:
main 1
main 2
main 3
C end
A end
B end
Task D: ForkJoinPool.commonPool-worker-3
D end
Final Result from D: D: Result A, Result B, Result C