如何优雅的关闭线程池?

Python012

如何优雅的关闭线程池?,第1张

线程池是系统资源,这篇文章主要介绍如何优雅关闭线程

相关API:

Runtime.addShutdownHook解释

如果你想在jvm关闭的时候进行内存清理、对象销毁等操作,或者仅仅想起个线程然后这个线程不会退出,你可以使用Runtime.addShutdownHook。

这个方法的作用就是在JVM中增加一个关闭的钩子。当程序正常退出、系统调用 System.exit方法或者虚拟机被关闭时才会执行系统中已经设置的所有钩子,当系统执行完这些钩子后,JVM才会关闭。所谓钩子,就是一个已初始化但并不启动的线程。JVM退出通常通过两种事件。

程序正常退出,例如最后一个非守护进程退出、使用System.exit()退出等

程序异常退出,例如使用Ctrl+C触发的中断、用户退出或系统关闭等系统事件等 , 详情见官方文档:https://docs.oracle.com/javase/8/docs/api/index.html

Guava解释

google退出的open sdk,提供多类并发api。

上两篇文章讲了@Configuration @Bean @Import注入线程池Bean,还有ApplicationRunner 和 CommandLineRunner接口去实现容器启动完成事件驱动,所以结合起来举个例子,在项目中如何注入、优雅关闭线程池。

如上图。

1.通过@Configuration @Bean注解去注入一个线程池<componentThreadPool>。

2.将线程池注册到注册中心<ThreadPoolRegistrationCenter>

3.在Spring容器启动完成观察者模式中,利用ApplicationRunner接口提供的run方法,添加jvm hook钩子,以做到jvm退出时能够优雅关闭线程池。

其中用到了guava的<MoreExecutors.shutdownAndAwaitTermination>,jdk<Runtime.getRuntime().addShutdownHook>等API

如图,API 中有解释,shutdown 允许之前已经提交但未执行或未完成的任务继续完成它,而 shutdownNow 阻止已经提交(但尚未运行的)的任务运行并且尝试停止正在运行的任务。

一句话,shutdown 优雅而不究既往,而shutdownNow 就像停电一般消灭所有既成事实。

通过Thread类中的isAlive()方法判断线程是否处于活动状态;

线程启动后,只要没有运行完毕,都会返回true;

除了上面一种还有两种;

1,通过Thread.activeCount()方法判断当前线程的线程组中活动线程的数目,为1时其他线程运行完毕;

2,通过java.util.concurrent.Executors中的方法创建一个线程池,用这个线程池来启动线程。启动所有要启动的线程后,执行线程池的shutdown()方法,即在所有线程执行完毕后关闭线程池。然后通过线程池的isTerminated()方法,判断线程池是否已经关闭。线程池成功关闭,就意味着所有线程已经运行完毕了;

例如;