面试题答案
一键面试thenRun
的线程调度:thenRun
方法是CompletableFuture
中的一个方法,用于在CompletableFuture
完成时执行一个无参数的Runnable
任务。- 如果
CompletableFuture
是由ForkJoinPool.commonPool()
(默认线程池)执行完成的,那么thenRun
所执行的任务也会在这个ForkJoinPool.commonPool()
中执行。 - 如果
CompletableFuture
是由自定义线程池执行完成的,并且这个自定义线程池的队列未满,那么thenRun
所执行的任务会被提交到这个自定义线程池执行。如果自定义线程池队列已满,任务提交可能会失败(取决于线程池的拒绝策略)。
- 在不同线程池中执行任务时
thenRun
方法的行为变化:- 当
CompletableFuture
在不同线程池中执行完成时,thenRun
所执行的任务默认会提交到完成CompletableFuture
的那个线程池执行,除非使用了其他方式来指定线程池。
- 当
- 代码示例:
import java.util.concurrent.*;
public class CompletableFutureThenRunExample {
public static void main(String[] args) {
ExecutorService executor1 = Executors.newFixedThreadPool(2);
ExecutorService executor2 = Executors.newFixedThreadPool(2);
CompletableFuture.supplyAsync(() -> {
System.out.println("Task in executor1 is running on thread: " + Thread.currentThread().getName());
return "Result from executor1";
}, executor1)
.thenRun(() -> {
System.out.println("thenRun task is running on thread: " + Thread.currentThread().getName());
})
.thenRunAsync(() -> {
System.out.println("thenRunAsync task (should be in another executor) is running on thread: " + Thread.currentThread().getName());
}, executor2)
.whenComplete((result, throwable) -> {
executor1.shutdown();
executor2.shutdown();
});
try {
executor1.awaitTermination(1, TimeUnit.MINUTES);
executor2.awaitTermination(1, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
在上述代码中:
supplyAsync
方法在executor1
线程池中执行任务。- 第一个
thenRun
方法会在executor1
线程池中执行,因为CompletableFuture
是由executor1
完成的。 thenRunAsync
方法指定了executor2
线程池,所以它会在executor2
线程池中执行。
注意,在实际应用中,要记得正确关闭线程池,如代码中使用shutdown
和awaitTermination
方法。