Java Spring调度程序关闭错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2730354/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring scheduler shutdown error
提问by Alex
During development a SPRING based scheduler in a tomcat container, I always get this logoutput at undeploy webapp or shutdown server:
在 tomcat 容器中开发基于 SPRING 的调度程序期间,我总是在取消部署 webapp 或关闭服务器时获得此日志输出:
Apr 28, 2010 4:21:33 PM org.apache.catalina.core.StandardService stop
INFO: Stopping service Catalina
Apr 28, 2010 4:21:33 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application 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.
Apr 28, 2010 4:21:33 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2] but has failed to stop it. This is very likely to create a memory leak.
Apr 28, 2010 4:21:33 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-3] but has failed to stop it. This is very likely to create a memory leak.
Apr 28, 2010 4:21:33 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-4] but has failed to stop it. This is very likely to create a memory leak.
Apr 28, 2010 4:21:33 PM org.apache.catalina.loader.WebappClassLoader clearReferencesThreads
SEVERE: A web application appears to have started a thread named [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-5] but has failed to stop it. This is very likely to create a memory leak.
.
.
.
SEVERE: A web application created a ThreadLocal with key of type [org.springframework.core.NamedThreadLocal] (value [Prototype beans currently in creation]) and a value of type [null] (value [null]) but failed to remove it when the web application was stopped. To prevent a memory leak, the ThreadLocal has been forcibly removed.
Apr 28, 2010 4:21:34 PM org.apache.coyote.http11.Http11Protocol destroy
INFO: Stopping Coyote HTTP/1.1 on http-8606
How can I fix this?
我怎样才能解决这个问题?
thank you stevedbrown
谢谢史蒂夫布朗
I add this listener to my webapp
我将此侦听器添加到我的 web 应用程序
public class ShutDownHook implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
BeanFactory bf = (BeanFactory) ContextLoader.getCurrentWebApplicationContext();
if (bf instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext)bf).close();
}
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
}
}
and my web.xml
和我的 web.xml
<listener>
<listener-class>pkg.utility.spring.ShutDownHook</listener-class>
</listener>
but the error is still there.
但错误仍然存在。
spring config:
弹簧配置:
<bean id="run" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="concurrent" value="false" />
<property name="targetObject" ref="scheduler" />
<property name="targetMethod" value="task" />
</bean>
<bean id="cronTrg" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="run" />
<property name="cronExpression" value="0/5 * * * * ?" />
</bean>
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean" destroy-method="destroy">
<property name="triggers">
<list>
<ref bean="cronTrg" />
</list>
</property>
</bean>
采纳答案by stevedbrown
You need to add a shutdown hook - see Registering a shutdown hook in Spring 2.5.
您需要添加一个关闭钩子 - 请参阅在 Spring 2.5 中注册一个关闭钩子。
In your case, you probably should add a context listener to your webapp that does this (web.xml entry for the listener + implementing class).
在您的情况下,您可能应该向执行此操作的 web 应用程序添加一个上下文侦听器(侦听器 + 实现类的 web.xml 条目)。
Use close, it's easiest.
使用close,这是最简单的。
((YourClass)yourObject).close();
回答by Collin Peters
Here is my solution as none of the ones that I found online worked. This is specifically to shutdown the Quartz scheduler with Spring & Tomcat
这是我的解决方案,因为我在网上找到的解决方案都不起作用。这是专门用 Spring & Tomcat 关闭 Quartz 调度器的
My explanation is here: http://forum.springsource.org/showthread.php?34672-Quartz-doesn-t-shutdown&p=370060#post370060
我的解释在这里:http: //forum.springsource.org/showthread.php?34672-Quartz-doesn-t-shutdown&p=370060#post370060
Basically what the problem seemed to be is that Quartz doesn't have enough time to cleanly shutdown and the waitForJobsToCompleteOnShutdown argument doesn't seem to help. So I implemented a custom shutdown listener in the webapp, get a reference to the scheduler and shut it down manually. And then wait for 1 second before proceeding.
基本上问题似乎是 Quartz 没有足够的时间干净地关闭并且 waitForJobsToCompleteOnShutdown 参数似乎没有帮助。所以我在 webapp 中实现了一个自定义关闭侦听器,获取对调度程序的引用并手动关闭它。然后等待 1 秒钟再继续。
public class ShutDownHook implements ServletContextListener
{
@Override
public void contextDestroyed(ServletContextEvent arg0)
{
try
{
// Get a reference to the Scheduler and shut it down
WebApplicationContext context = ContextLoader.getCurrentWebApplicationContext();
Scheduler scheduler = (Scheduler) context.getBean("quartzSchedulerFactory");
scheduler.shutdown(true);
// Sleep for a bit so that we don't get any errors
Thread.sleep(1000);
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void contextInitialized(ServletContextEvent arg0)
{
}
回答by StefanR
Imho this is an issue of the quartz scheduler. I filed a bug https://jira.terracotta.org/jira/browse/QTZ-192. As a workaround the sleep() solution suggested by Colin Peters works for me. To not trigger the shutdown twice one could also add the sleep to Spring's SchedulerFactoryBean:
恕我直言,这是石英调度程序的问题。我提交了一个错误https://jira.terracotta.org/jira/browse/QTZ-192。作为一种解决方法,Colin Peters 建议的 sleep() 解决方案对我有用。为了不触发两次关闭,还可以将睡眠添加到 Spring 的 SchedulerFactoryBean:
import org.quartz.SchedulerException;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
public class SchedulerFactoryBeanWithShutdownDelay extends SchedulerFactoryBean{
@Override
public void destroy() throws SchedulerException {
super.destroy();
// TODO: Ugly workaround for https://jira.terracotta.org/jira/browse/QTZ-192
try {
Thread.sleep( 1000 );
} catch( InterruptedException e ) {
throw new RuntimeException( e );
}
}
}
回答by Martin
The only way to ensure that threads are terminated, is to interrupt and join them.
确保线程终止的唯一方法是中断并加入它们。
This can by done by implementing org.quartz.InterruptableJob
, as described in the answer to the question How to prevent a memory leak in quartz [?].
这可以通过实现来完成org.quartz.InterruptableJob
,如问题如何防止石英中的内存泄漏 [?]的答案中所述。