新客立减

如何优雅的关闭

Java

线程池

⾯试中经常会问到,创建⼀个线程池需要哪些参数啊,线程池的⼯作原理啊,却很少会问到线程池如何安全关闭的。

也正是因为⼤家不是很关注这块,即便是⼯作三四年的⼈,也会有因为线程池关闭不合理,导致应⽤⽆法正常

stop

的情况,还有出现⼀些报

错的问题。

本篇就以

ThreadPoolExecutor

为例,来介绍下如何优雅的关闭线程池。

01 

线程中断

在介绍线程池关闭之前,先介绍下

Thread

interrupt

在程序中,我们是不能随便中断⼀个线程的,因为这是极其不安全的操作,我们⽆法知道这个线程正运⾏在什么状态,它可能持有某把锁,

强⾏中断可能导致锁不能释放的问题;或者线程可能在操作数据库,强⾏中断导致数据不⼀致混乱的问题。正因此,

JAVA

⾥将

Thread

stop

⽅法设置为过时,以禁⽌⼤家使⽤。

⼀个线程什么时候可以退出呢?当然只有线程⾃⼰才能知道。

所以我们这⾥要说的

Thread

interrrupt

⽅法,本质不是⽤来中断⼀个线程。是将线程设置⼀个中断状态。

当我们调⽤线程的

interrupt

⽅法,它有两个作⽤:

1

、如果此线程处于阻塞状态

(

⽐如调⽤了

wait

⽅法,

io

等待

)

,则会⽴马退出阻塞,并抛出

InterruptedException

异常,线程就可以通过捕获

InterruptedException

来做⼀定的处理,然后让线程退出。

2

、如果此线程正处于运⾏之中,则线程不受任何影响,继续运⾏,仅仅是线程的中断标记被设置为

true

。所以线程要在适当的位置通过调⽤

isInterrupted

⽅法来查看⾃⼰是否被中断,并做退出操作。

注:

如果线程的

interrupt

⽅法先被调⽤,然后线程调⽤阻塞⽅法进⼊阻塞状态,

InterruptedException

异常依旧会抛出。

如果线程捕获

InterruptedException

异常后,继续调⽤阻塞⽅法,将不再触发

InterruptedException

异常。

02 

线程池的关闭

线程池提供了两个关闭⽅法,

shutdownNow

shuwdown

⽅法。

shutdownNow

⽅法的解释是:线程池拒接收新提交的任务,同时⽴马关闭线程池,线程池⾥的任务不再执⾏。

shutdown

⽅法的解释是:线程池拒接收新提交的任务,同时等待线程池⾥的任务执⾏完毕后关闭线程池。

以上的说法虽然没错,但是还有很多的细节,⽐如调⽤

shutdown

⽅法后,正在执⾏任务的线程做出什么反应?正在等待任务的线程⼜做出

什么反应?线程在什么情况下才会彻底退出。如果不了解这些细节,在关闭线程池时就难免遇到,像线程池关闭不了,关闭线程池出现报错

等情况。

再说这些关闭线程池细节之前,需要强调⼀点的是,调⽤完

shutdownNow

shuwdown

⽅法后,并不代表线程池已经完成关闭操作,它只是

异步的通知线程池进⾏关闭处理。如果要同步等待线程池彻底关闭后才继续往下执⾏,需要调⽤

awaitTermination

⽅法进⾏同步等待。

有了以上介绍,下⾯就结合线程池源码,分别说说这两个线程池关闭⽅法的⼀些实现细节。

shutdownNow

我们看⼀下

shutdownNow

⽅法的源码: