任务队列处理逻辑
- SHUTDOWN状态:
- 当线程池进入SHUTDOWN状态时,不再接受新任务,但会继续执行任务队列中已有的任务。
- 任务队列中的任务会按照其入队顺序,由工作线程依次取出并执行。
- STOP状态:
- 线程池进入STOP状态时,不仅不再接受新任务,还会尝试停止正在执行的任务,并且会清空任务队列。
工作线程处理逻辑
- SHUTDOWN状态:
- 工作线程在执行完当前任务后,会去任务队列中获取新的任务继续执行。
- 如果任务队列中没有任务,工作线程会进入等待状态(通过
await()
方法等机制),直到有新任务加入队列或者线程池被关闭。
- STOP状态:
- 对于正在执行任务的工作线程,线程池会调用
interrupt()
方法中断线程。工作线程需要能够响应中断,例如在合适的地方检查Thread.currentThread().isInterrupted()
,并进行相应的清理和终止操作。
- 对于处于等待状态的工作线程,
interrupt()
方法会唤醒它们,使其可以检查中断状态并进行终止操作。
可能遇到的问题及解决方案
- 任务无法正常停止:
- 问题:在STOP状态下,有些任务可能不响应中断,导致无法正常停止。
- 解决方案:在编写任务代码时,要确保任务能够正确响应中断。例如,在循环中检查
Thread.currentThread().isInterrupted()
,并在适当的时候终止任务。对于一些无法响应中断的阻塞操作(如Socket.accept()
),可以使用带有超时的方法,或者使用Selector
等非阻塞方式替代。
- 任务队列残留任务:
- 问题:在某些情况下,可能会出现任务队列中的任务没有被完全执行就被终止的情况。
- 解决方案:在关闭线程池之前,可以先调用
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();
}
- 工作线程资源泄漏:
- 问题:如果工作线程在异常情况下没有正确清理资源,可能会导致资源泄漏。
- 解决方案:在工作线程的任务代码中,使用
try - finally
块来确保无论任务执行成功还是失败,都能正确释放资源,如关闭文件句柄、数据库连接等。