最近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) { System.out.println("ContextFinalizer:SEVERE problem cleaning up: " + e.getMessage()); 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(); } } }
时间: 2024-10-18 01:58:07