经常碰到shutdown之后不能完全关闭, 每次kill -9 操作麻烦且破换程序处理, 借鉴网上资料作下整理:
1. ps -aux | grep 8089/bin 找到遗留的进程PID
2. 使用jdk自带的jstack pid 查看具体线程
3. ServletContextListener服务监听器的销毁方法中, 增加关闭线程的处理:
public class SystemContextListener implements ServletContextListener
{
private static Logger logger = Logger.getLogger(SystemContextListener.class);
// 需要强制关闭的线程名
public static final List<String> MANUAL_DESTROY_THREAD_IDENTIFIERS = Arrays.asList("QuartzScheduler", "scheduler_Worker", "miiapQuartzFactory_QuartzSchedulerThread", "MultiThreadedHttpConnectionManager cleanup");
@Override
public void contextDestroyed(ServletContextEvent contextEvent) {
// 关闭T2接口服务
T2Interface.stop();
destroyJDBCDrivers();
destroySpecifyThreads();
}
@Override
public void contextInitialized(ServletContextEvent contextEvent)
{
try
{
// 初始化spring容器
SpringBeanFactory.init("classpath*:application*.xml");
// 初始化, 读取系统配置
ConfigProperties.initALL();
// 启动T2接口服务
T2Interface.initConfigs();
T2Interface.start();
}
catch (Exception e)
{
e.printStackTrace();
logger.error(e.getMessage(), e);
}
}
/**
* 注销线程
*/
private void destroySpecifyThreads() {
final Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) {
// 默认会把所有调度相关的线程关闭
if (needManualDestroy(thread) || (thread.getName()!= null && thread.getName().toUpperCase().indexOf("QUARTZ")!= -1)) {
synchronized (this) {
try {
thread.stop();
logger.debug(String.format("Destroy %s successful", thread));
} catch (Exception e) {
logger.warn(String.format("Destroy %s error", thread), e);
}
}
}
}
}
/**
* 需要销毁的线程名
* @param thread
* @return
*/
private boolean needManualDestroy(Thread thread) {
final String threadName = thread.getName();
for (String manualDestroyThreadIdentifier : MANUAL_DESTROY_THREAD_IDENTIFIERS) {
if (threadName.contains(manualDestroyThreadIdentifier)) {
return true;
}
}
return false;
}
/**
* 注销JDBC驱动
*/
private void destroyJDBCDrivers() {
final Enumeration<Driver> drivers = DriverManager.getDrivers();
Driver driver;
while (drivers.hasMoreElements()) {
driver = drivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
logger.debug(String.format("Deregister JDBC driver %s successful", driver));
} catch (SQLException e) {
logger.warn(String.format("Deregister JDBC driver %s error", driver), e);
}
}
}
}