面试题答案
一键面试设计思路
- 异常分类与捕获:在任务执行逻辑中,使用try - catch块捕获各类异常,区分资源耗尽异常(如
OutOfMemoryError
等)、任务依赖失败异常(如自定义的依赖检查异常)等不同类型异常。 - 线程池监控:利用
ThreadPoolExecutor
的监控方法,如getActiveCount
、getQueue
等方法,实时了解线程池状态,以便在异常发生时能基于线程池当前情况进行处理。 - 恢复策略:
- 资源耗尽:尝试释放一些非关键资源(如缓存数据等),或者等待一定时间后重新提交任务。
- 任务依赖失败:根据依赖关系重新检查并建立依赖,如重新获取数据库连接、重新加载配置等,然后重试任务。
- 日志记录:详细记录异常信息,包括异常类型、发生时间、任务相关信息等,方便后续排查问题。
- 限流与降级:在异常频发时,采取限流措施减少任务提交频率,或进行降级处理,如返回默认值等,避免系统进一步崩溃。
关键代码示例
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class ExceptionRecoveryThreadPool {
private static final int CORE_POOL_SIZE = 5;
private static final int MAX_POOL_SIZE = 10;
private static final long KEEP_ALIVE_TIME = 10;
private static final TimeUnit TIME_UNIT = TimeUnit.SECONDS;
private static final BlockingQueue<Runnable> WORK_QUEUE = new LinkedBlockingQueue<>(100);
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE,
KEEP_ALIVE_TIME,
TIME_UNIT,
WORK_QUEUE);
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
int taskNumber = i;
executor.submit(() -> {
try {
// 模拟业务逻辑
if (taskNumber % 3 == 0) {
throw new RuntimeException("模拟任务依赖失败异常");
}
System.out.println("任务 " + taskNumber + " 正常执行");
} catch (Exception e) {
handleException(e, taskNumber);
}
});
}
executor.shutdown();
}
private static void handleException(Exception e, int taskNumber) {
// 记录异常日志
System.err.println("任务 " + taskNumber + " 发生异常: " + e.getMessage());
if (e instanceof RuntimeException) {
// 模拟任务依赖失败的恢复策略
System.err.println("任务 " + taskNumber + " 依赖失败,尝试重新执行");
// 这里可以添加重新建立依赖、重试等逻辑
executor.submit(() -> {
try {
System.out.println("任务 " + taskNumber + " 重新执行成功");
} catch (Exception reE) {
System.err.println("任务 " + taskNumber + " 重新执行再次失败: " + reE.getMessage());
}
});
} else {
// 其他异常处理
System.err.println("任务 " + taskNumber + " 发生其他异常,暂不处理");
}
}
}
总结
通过上述设计思路和代码示例,我们构建了一个具备异常恢复机制的线程池。通过对异常的分类处理、线程池监控、合理的恢复策略、日志记录以及限流降级等手段,尽可能保证系统在高并发和复杂业务逻辑下出现异常时能够快速、稳定恢复,同时减少对正常业务处理的影响。