方案一:shutdown、shutdownNow
ExecutorService 接口定义了线程池任务提交、获取线程池状态、线程池停止的方法等。
JDK 1.8 中,线程池的停止一般使用 shutdown()、shutdownNow()方法。
shutdown和shutdownNow的异同
- 调用 shutdown() 和 shutdownNow() 方法关闭线程池,线程池都无法接收新的任务。
- shutdown() 方法会继续执行正在执行未完成的任务,shutdownNow() 方法会尝试停止所有正在执行的任务。
- shutdown() 方法没有返回值,shutdownNow() 方法返回等待执行的任务列表。
- awaitTermination(long timeout, TimeUnit unit) 方法可以获取线程池是否已经关闭,需要配合 shutdown() 使用。
- shutdownNow() 不一定能够立马结束线程池,该方法会尝试停止所有正在执行的任务,通过调用 Thread.interrupt() 方法来实现的,如果线程中没有 sleep() 、wait()、Condition、定时锁等应用,interrupt() 方法是无法中断当前的线程的。
方案二:执行完毕后空转线程的超时时间设置
keepAliveTime:非核心线程闲置的超时时间。超过这个时间就会回收。
如果任务很多,每个任务执行时间很短,可以调大keepAliveTime提高线程利用率
面试题:如何设置核心线程的超时时间?
先设置allowCoreThreadTimeOut属性为true,那么keepAliveTime就会应用到核心线程。