面试题答案
一键面试- 异常处理:
- 在
afterExecute
方法中,需要重点关注任务执行过程中抛出的异常。因为afterExecute
方法在任务执行结束后调用,此时任务执行过程中的异常可能导致程序出现未处理的错误情况。通过在afterExecute
中捕获并恰当处理异常(例如记录详细的异常日志,以便排查问题),可以避免异常泄露,增强程序的健壮性。例如:
@Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); if (t != null) { System.err.println("Task execution failed: " + t.getMessage()); t.printStackTrace(); } }
- 在
- 资源清理:
- 如果任务在执行过程中占用了一些资源(如文件句柄、数据库连接等),在
afterExecute
方法中需要确保这些资源被正确清理。因为任务执行完毕后,如果资源未及时释放,可能会导致资源泄漏,长时间运行后可能耗尽系统资源。例如,对于一个使用FileInputStream
读取文件的任务,在afterExecute
中要确保FileInputStream
被关闭:
@Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); // 假设任务执行时使用了FileInputStream,这里清理相关资源 if (r instanceof MyTask) { MyTask task = (MyTask) r; try { task.getFileInputStream().close(); } catch (IOException e) { System.err.println("Failed to close file input stream: " + e.getMessage()); } } }
- 如果任务在执行过程中占用了一些资源(如文件句柄、数据库连接等),在
- 线程状态与上下文:
- 要注意线程池中的线程在任务执行完后的状态以及上下文。
afterExecute
执行时,线程可能马上被复用去执行下一个任务。如果需要在任务间传递一些线程局部变量(ThreadLocal
)相关的上下文信息,需要正确处理,确保不会对后续任务产生干扰。比如,如果一个任务在执行过程中设置了ThreadLocal
的用户身份信息,在afterExecute
中如果不清理或正确处理,下一个任务可能会使用到错误的用户身份信息。例如:
private static final ThreadLocal<String> userContext = new ThreadLocal<>(); @Override protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); userContext.remove(); }
- 要注意线程池中的线程在任务执行完后的状态以及上下文。