最近tomcat走普通的关闭方式无法正常关闭,会报一些Error,用的是Tomcat7,据说是Tomcat7在关闭的时候加了一些检查线程泄漏内存泄露的东西
总结起来,在我项目中有这么几个原因会导致关闭不了:
1、使用了@Scheduled注解
最后查出来原因是因为在bean里面使用了 @Scheduled 注解,而Tomcat关闭的时候,spring并不能主动关闭这些Schedule,也就是说这注解有缺陷,慎用。
替代方法就是放弃spring的Scheduled注解方式使用quartz,这里我把所有的spring注解计划任务换回了配置文件:
<bean id="syncProgramQuartz" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"><property name="targetObject" ref="taskProgramSync"></property><property name="targetMethod" value="sync"></property><property name="concurrent" value="false"></property></bean><bean id="syncProgramQuartzTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean"><property name="jobDetail" ref="syncProgramQuartz"></property><property name="cronExpression"><value>${SYN_PROGRAM_TASK_CRON}</value></property></bean><bean name="startQuertz" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"><property name="triggers"><list><ref bean="syncProgramQuartzTrigger" /></list></property></bean>
这样就不报 pool-xxxx-1无法关闭之类的错误了。
2、连接池没有手动关闭
这个也是在自定义的Listener里面处理,代码如下
new Thread() {public void run() {Enumeration<Driver> drivers = DriverManager.getDrivers(); while (drivers.hasMoreElements()) { Driver driver = drivers.nextElement(); try { DriverManager.deregisterDriver(driver); } catch (SQLException e) { e.printStackTrace(); } } }}.start();
3、AbandonedConnectionCleanupThread单独关闭,这个在关完连接池后就顺便一起关了吧
try {AbandonedConnectionCleanupThread.shutdown();} catch (InterruptedException e) {e.printStackTrace();}
一般做完以上三步就差不多了。
4、个别线程强行阻碍
对于这种管不了的线程我们就根据其线程名将其关闭
Set<Thread> threads = Thread.getAllStackTraces().keySet(); for (Thread thread : threads) { if(thread.getName().equals("xxxxxxthread")){ try { thread.interrupt();System.out.println(thread.getName()+" is stopped");return; } catch (Exception e) { System.out.println(thread.getName()+" stop error");e.printStackTrace();} } }