出错信息

22-Sep-2017 06:19:51.064 WARNING [main] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [license] appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
java.lang.Object.wait(Native Method)
org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:568)

问题分析:servlet容器关闭时发现Quartz定时器线程还在执行,对其无所适从,不懂怎么办只能强行关闭。

解决思路,在关闭容器时的contextDestroyed事件里检测ServletContext里Quartz相关属性,找到Bean然后调用它的方法结束掉。

解决方法:

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration; import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener; import org.apache.logging.log4j.web.Log4jWebSupport;
import org.quartz.impl.StdScheduler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils; @WebListener
public class AppContextListener implements ServletContextListener
{ public void contextDestroyed(ServletContextEvent event) {
logger.info("Destroying Context..."); try {
WebApplicationContext context = (WebApplicationContext) event.getServletContext().getAttribute(
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); Enumeration<String> attributes = event.getServletContext().getAttributeNames();
while(attributes.hasMoreElements())
{
String attr = attributes.nextElement();
Object prop = event.getServletContext().getAttribute(attr);
logger.info("attribute.name: {},class:{}, value:{}",attr,prop.getClass().getName(),prop);
} String[] beanNames = context.getBeanDefinitionNames(); for(String beanName:beanNames)
{
Object bean = context.getBean(beanName);
logger.info("found bean attribute in ServletContext,name:{},class:{},value:{}",
beanName,bean.getClass().getName(),bean);
if(beanName.contains("quartz")&&beanName.contains("Scheduler")){
StdScheduler scheduler = (StdScheduler)context.getBean("org.springframework.scheduling.quartz.SchedulerFactoryBean#0");
logger.info("发现quartz定时任务");
logger.info("beanName:{},className:{}",scheduler,scheduler.getClass().getName());
if(scheduler.isStarted())
{
logger.info("Quartz:waiting for job complete...");
scheduler.shutdown(true);
logger.info("Quartz:all threads are complete and exited...");
}
}
} } catch (Exception e) {
logger.error("Error Destroying Context", e);
}
} //https://stackoverflow.com/questions/23936162/register-shutdownhook-in-web-application
public void contextInitialized(ServletContextEvent event) {
//ServletContext context = event.getServletContext();
//System.setProperty("rootPath", context.getRealPath("/"));
//LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
//ctx.reconfigure();
/*logger.info("global setting,rootPath:{}",rootPath);
logger.info("deployed on architecture:{},operation System:{},version:{}",
System.getProperty("os.arch"), System.getProperty("os.name"),
System.getProperty("os.version"));
Debugger.dump();
logger.info("app startup completed....");*/
}
|

关闭tomcat日志如下:

其他解决方法:Spring配置文件

笔者经过实践,发现在spring配置文件里设置参数也可以达到以上效果

  <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="simpleTrigger" />
<ref bean="cronTrigger" />
<ref bean="secondCronTrigger"/>
</list>
</property>
<property name="waitForJobsToCompleteOnShutdown" value="true"/>
</bean>
<property name="waitForJobsToCompleteOnShutdown" value="true"/>可以在web关闭的时候关闭线程

Spring整合quartz关闭,关闭Tomcat Servlet容器时内存泄漏的更多相关文章

  1. 初识quartz 并分析 项目中spring整合quartz的配置【原创+转载】

    初识quartz 并分析 项目中spring整合quartz的配置[原创+转载]2018年01月29日 12:08:07 守望dfdfdf 阅读数:114 标签: quartz 更多个人分类: 工具 ...

  2. spring整合quartz并持久化

    spring整合quartz有两种方式: 一.常见是使用配置文件,将定时任务保存到内存中 简单示例: <!-- 短信催还提醒任务调度 --> <bean id="overd ...

  3. Spring整合Quartz定时任务执行2次,Spring定时任务执行2次

    Spring整合Quartz定时任务执行2次,Spring定时任务执行2次 >>>>>>>>>>>>>>>&g ...

  4. spring整合quartz框架

    spring整合quartz: 网上也有很多教程,好多都是基于配置方式,我们使用当然怎么简单就怎么用,所以这里介绍基于注解方式整合quartz.前提:你需要有一个能运行的web项目. 1.引依赖: & ...

  5. 使用Spring整合Quartz轻松完成定时任务

    一.背景 上次我们介绍了如何使用Spring Task进行完成定时任务的编写,这次我们使用Spring整合Quartz的方式来再一次实现定时任务的开发,以下奉上开发步骤及注意事项等. 二.开发环境及必 ...

  6. spring整合quartz时间任务调度框架

    spring整合quartz框架 1.创建maven工程 2.导入jar包(pom.xml) <dependencies> <dependency> <groupId&g ...

  7. Spring整合Quartz定时任务 在集群、分布式系统中的应用(Mysql数据库环境)

    Spring整合Quartz定时任务 在集群.分布式系统中的应用(Mysql数据库环境)   转载:http://www.cnblogs.com/jiafuwei/p/6145280.html 单个Q ...

  8. Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入

    Spring quartz Job不能依赖注入,Spring整合quartz Job任务不能注入 Spring4整合quartz2.2.3中Job任务使用@Autowired不能注入 >> ...

  9. 使用spring整合Quartz实现—定时器

    使用spring整合Quartz实现—定时器(Maven项目做演示) 不基于特定的基类的方法 一,开发环境以及依赖的jar包 Spring 4.2.6.RELEASE Maven 3.3.9 Jdk ...

随机推荐

  1. MyBatis注解-动态SQL 一个 SqlProvider的demo

    Provider动态语言注解 MyBatis提供了多个注解如:@InsertProvider,@UpdateProvider,@DeleteProvider和@SelectProvider,这些都是建 ...

  2. C++内存泄漏检测工具

    C++内存泄漏检测工具 1.VC自带的CRT:_CrtCheckMemory   调试器和 CRT 调试堆函数 1.1用法: /************************************ ...

  3. (Python基础)文件操作

    对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 现有文件如下 命名为7 years Once I was seven years old my momma t ...

  4. shell脚本实现telnet测试服务端口

    备注,使用方法:当前目录下要存在需要测试的地址端口的文件ip.txt,例子:cat ip.txt141.12.65.17 7500 #!/bin/bashcur_dir=$(pwd)ipfile=$c ...

  5. 【C语音基础】printf()用法

    printf() -- 将变量的内容输出到显示器上 四种用法 1.printf("字符串\n"); 2.printf("输出控制符",输出参数); 3.prin ...

  6. springboot学习随笔(一):springboot环境构建:eclipse+maven+jdk1.8

    一:所需环境 1.jdk1.8(配置环境变量,可自行搜索相关文档) 2.maven(maven的配置不在赘述,可自行搜索相关文档) 3.eclipse(第三种方式,eclipse集成sts时需要,直接 ...

  7. reg 和wire 区别

    reg相当于存储单元,wire相当于物理连线 Verilog 中变量的物理数据分为线型和寄存器型.这两种类型的变量在定义时要设置位宽,缺省为1位.变量的每一位可以是0,1,X,Z.其中x代表一个未被预 ...

  8. base编码解码

    function b64EncodeUnicode(str) { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, func ...

  9. [C++]数组指针,数组引用,函数指针

    数组指针是指一个指向数组的指针,例如有一个数组指针p指向一个数组a[],则 *p是取到这个数组,也就是说 *p=a,因此 **p =a[0], 它的定义为: ]; ]=&a; (*c)表示它是 ...

  10. Centos7的防火墙关闭

    第一步.centos7安装service 第二步. 或者可以不用service,有另一个办法.