Spring Quartz计划任务在一段时间后停止运行

时间:2015-06-05 05:38:50

标签: java multithreading spring timer quartz-scheduler

我在webapp中运行了一个Quartz计时器任务。 该任务每10秒检查一次数据库中是否存在特定表中的新数据。

<bean id="triggerCheckEvents" class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail">
    <bean id="jobCheckEvents" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="checkEvents" />
        <property name="targetMethod" value="execute" />
        <property name="concurrent" value="false" />
    </bean>
</property>
<property name="startDelay" value="${checkEvent.startDelay}" />
<property name="repeatInterval" value="${checkEvent.repeatDelay}" />

大约每隔一天左右,计时器停止运行。我有点肯定它在数据库中做某事时会卡住。但是,重新启动数据库似乎对恢复计时器的正常运行没有影响。没有异常被抛出。所以没有堆栈跟踪。

虽然我试图找到根本原因。我认为,I / O问题必然会在长时间运行的过程中发生。所以这个问题的正确解决方案就是拥有某种看门狗,比如说,在超时后杀死线程,产生一个新的步骤并按照计划继续计时器。

当任务在指定的时间范围内无法返回时,是否有办法终止计划任务并创建新实例?

  

我没有尝试使用数据库修复此特定错误。因为明天一些其他错误可能会阻止线程。我正在寻找一种高水平的解决方案,可以终止胎面或做任何事情   需要释放被挂起的计时器线程阻塞的资源   创建一个新的实例。长期以来意外的问题是不可避免的   运行过程。正确的解决方案不是研究和修复众多问题   个别问题,当他们出现时,但有一个策略   即使发生错误也能恢复正常功能。

1 个答案:

答案 0 :(得分:2)

我遇到类似的问题,其中一项任务被阻止。一种方法是:在每次调用任务时,在新线程中执行实际操作并使任务的线程等待新线程完成(直到超过最大允许时间)。这样任务永远不会被阻止。

    public void work(JobExecutionContext ctx) {
    Thread t = new Thread(new Runnable() {
        public void run() {
            doSomethingInNewThread();
        }
    }, "ThreadName-" + System.currentTimeMillis());
    t.start();
    try {
        t.join(maxAllowedTime);
        if (t.isAlive()) {
            logger.warn("Tasks child thread "
                    + t.getName()
                    + "is still alive, potential thread block.");
            //TBD - if needed, add logic to terminate child thread
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}