面试题答案
一键面试优化思路
- 自定义线程池:创建一个合适大小的线程池,避免使用默认的 ForkJoinPool.commonPool(),因为它可能不适合高并发应用的特定需求。根据系统的 CPU 核心数、内存大小以及任务特性来调整线程池的参数,如核心线程数、最大线程数、队列容量等。
- 合理配置任务队列:选择合适的任务队列类型,如 ArrayBlockingQueue、LinkedBlockingQueue 等。根据任务的优先级、预计任务数量等因素来设置队列容量,防止队列无限增长导致内存耗尽。
- 复用 CompletableFuture:避免在每次 thenRun 调用时创建新的 CompletableFuture,尽可能复用已有的实例,减少对象创建开销。
- 任务拆分与合并:对于复杂任务,考虑拆分成多个小任务并行处理,处理完成后再合并结果,提高整体吞吐量。
关键代码片段示例
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class CompletableFutureOptimization {
// 自定义线程池
private static final ExecutorService executorService = new ThreadPoolExecutor(
10, // 核心线程数
50, // 最大线程数
60L, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), // 任务队列
new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);
public static void main(String[] args) {
// 模拟大量异步任务
IntStream.range(0, 1000)
.mapToObj(i -> CompletableFuture.supplyAsync(() -> {
// 模拟异步计算
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return i;
}, executorService)
.thenRun(() -> {
// 任务完成后的处理
System.out.println("Task " + i + " completed.");
})
)
.collect(Collectors.toList())
.forEach(CompletableFuture::join);
// 优雅关闭线程池
executorService.shutdown();
try {
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
executorService.shutdownNow();
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
System.err.println("Pool did not terminate");
}
}
} catch (InterruptedException ie) {
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
在上述代码中:
- 创建了一个自定义的
ThreadPoolExecutor
,设置了核心线程数、最大线程数、存活时间、任务队列以及拒绝策略。 - 使用
CompletableFuture.supplyAsync
方法将异步任务提交到自定义线程池执行,然后通过thenRun
方法处理任务完成后的逻辑。 - 最后通过
executorService.shutdown()
和executorService.awaitTermination()
方法优雅关闭线程池,确保所有任务执行完毕。