MST

星途 面试题库

面试题:Java线程池运行状态转换及资源管理

当Java线程池从运行状态转换到其他状态(如SHUTDOWN状态)时,线程池中的任务和线程资源是如何管理的?请详细说明任务队列、工作线程的处理逻辑以及可能会遇到的问题及解决方案。
46.7万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

任务队列处理逻辑

  1. SHUTDOWN状态
    • 当线程池进入SHUTDOWN状态时,不再接受新任务,但会继续执行任务队列中已有的任务。
    • 任务队列中的任务会按照其入队顺序,由工作线程依次取出并执行。
  2. STOP状态
    • 线程池进入STOP状态时,不仅不再接受新任务,还会尝试停止正在执行的任务,并且会清空任务队列。

工作线程处理逻辑

  1. SHUTDOWN状态
    • 工作线程在执行完当前任务后,会去任务队列中获取新的任务继续执行。
    • 如果任务队列中没有任务,工作线程会进入等待状态(通过await()方法等机制),直到有新任务加入队列或者线程池被关闭。
  2. STOP状态
    • 对于正在执行任务的工作线程,线程池会调用interrupt()方法中断线程。工作线程需要能够响应中断,例如在合适的地方检查Thread.currentThread().isInterrupted(),并进行相应的清理和终止操作。
    • 对于处于等待状态的工作线程,interrupt()方法会唤醒它们,使其可以检查中断状态并进行终止操作。

可能遇到的问题及解决方案

  1. 任务无法正常停止
    • 问题:在STOP状态下,有些任务可能不响应中断,导致无法正常停止。
    • 解决方案:在编写任务代码时,要确保任务能够正确响应中断。例如,在循环中检查Thread.currentThread().isInterrupted(),并在适当的时候终止任务。对于一些无法响应中断的阻塞操作(如Socket.accept()),可以使用带有超时的方法,或者使用Selector等非阻塞方式替代。
  2. 任务队列残留任务
    • 问题:在某些情况下,可能会出现任务队列中的任务没有被完全执行就被终止的情况。
    • 解决方案:在关闭线程池之前,可以先调用awaitTermination()方法,设置一个合理的超时时间,等待线程池中的任务执行完毕。例如:
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 提交任务
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();
}
  1. 工作线程资源泄漏
    • 问题:如果工作线程在异常情况下没有正确清理资源,可能会导致资源泄漏。
    • 解决方案:在工作线程的任务代码中,使用try - finally块来确保无论任务执行成功还是失败,都能正确释放资源,如关闭文件句柄、数据库连接等。