Tomcat热部署,Web工程中线程没有终止

近期项目中,用 jenkins 热部署 web工程时,发现工程中静态持有的线程(将ScheduledExecutorService定时任务存储在静态Map中),导致不定时出现数据库访问事务关闭异常,如下:org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: EntityManagerFactory is closed

看到该问题,一直认为是操作数据库的类没有事务声明,所以在类上加上@Transactional,但没生效。并且程序不定期的调用工程中的Runnable类,然后报以上错误。明明只有一个线程,却出现多个线程运行,猜想应该是之前热部署时,存储在静态资源中的定时线程没有清除。重启Tomcat,发现不会报错了。故定位为Tomcat热部署,静态资源为释放。

猜想:遗留线程未释放,仍在运行,此时操作数据库,出现创建事务失败的异常,应该是web工程热部署后,Spring的事务管理已失效,无法创建事务。

解决方法

(1)使用Java EE5中的注解@PreDestroy

(2)使用Spring中的DisposableBean或配置destroy-method。(类实现 DisposableBean 接口,在 destroy() 方法中实现资源释放)

参考:

深入理解 Spring 事务原理

Spring事务管理详解

透彻的掌握 Spring 中@transactional 的使用

jenkins tomcat热部署,任务线程重复启动的解决方法

注解@PostConstruct与@PreDestroy详解及实例

Spring@PostConstruct和@PreDestroy实例

Spring Bean InitializingBean和DisposableBean实例  

 

 

posted @ 2018-03-01 21:18  水木竹水  阅读(1629)  评论(0编辑  收藏  举报