面试题答案
一键面试线程池参数配置
- 核心线程数:根据任务类型和系统资源确定。如果是I/O密集型任务,核心线程数可设置为
2 * CPU核心数
;如果是CPU密集型任务,核心线程数可设置为CPU核心数 + 1
。例如:
int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
- 最大线程数:一般对于I/O密集型任务,最大线程数可以适当增大,比如
4 * CPU核心数
;对于CPU密集型任务,最大线程数可与核心线程数相同或稍大。例如:
int maximumPoolSize = 2 * Runtime.getRuntime().availableProcessors();
- 线程存活时间:设置线程在没有任务时保持存活的时间,对于使用CachedThreadPool这种动态创建和销毁线程的场景较为重要,可设为
5L
,单位TimeUnit.SECONDS
等。例如:
long keepAliveTime = 5L;
TimeUnit unit = TimeUnit.SECONDS;
- 队列容量:根据任务到达速率和处理速率调整。如果任务到达速率稳定且处理速率能跟上,队列容量可设置适中,如
100
。例如:
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(100);
- 线程工厂:可自定义线程工厂来设置线程名称等属性,方便调试。例如:
ThreadFactory threadFactory = Executors.defaultThreadFactory();
- 拒绝策略:根据业务需求选择,常见的有
AbortPolicy
(默认,直接抛出异常)、CallerRunsPolicy
(调用者线程执行任务)、DiscardPolicy
(丢弃任务)、DiscardOldestPolicy
(丢弃队列最老的任务)。例如:
RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
然后创建线程池:
ThreadPoolExecutor executor = new ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
unit,
workQueue,
threadFactory,
handler);
异常捕获与处理
- 使用
exceptionally
方法:
CompletableFuture.supplyAsync(() -> {
// 异步任务,可能抛出异常
if (Math.random() > 0.5) {
throw new RuntimeException("模拟异常");
}
return "任务成功结果";
}, executor)
.exceptionally(ex -> {
System.out.println("捕获到异常: " + ex.getMessage());
return "默认值";
})
.thenAccept(System.out::println);
- 使用
whenComplete
方法:
CompletableFuture.supplyAsync(() -> {
// 异步任务,可能抛出异常
if (Math.random() > 0.5) {
throw new RuntimeException("模拟异常");
}
return "任务成功结果";
}, executor)
.whenComplete((result, ex) -> {
if (ex != null) {
System.out.println("捕获到异常: " + ex.getMessage());
} else {
System.out.println("任务结果: " + result);
}
});
- 使用
handle
方法:
CompletableFuture.supplyAsync(() -> {
// 异步任务,可能抛出异常
if (Math.random() > 0.5) {
throw new RuntimeException("模拟异常");
}
return "任务成功结果";
}, executor)
.handle((result, ex) -> {
if (ex != null) {
System.out.println("捕获到异常: " + ex.getMessage());
return "默认值";
}
return result;
})
.thenAccept(System.out::println);