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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 12:13:43  来源:igfitidea点击:

Spring scheduler shutdown error

javaspringtomcatquartz-scheduler

提问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,如问题如何防止石英中的内存泄漏 [?]的答案中所述。