恢复卡住的石英作业

时间:2017-03-06 13:21:31

标签: java multithreading quartz-scheduler

我正面临着一些卡住的石英工作,例如试图永远连接。我正在使用一种方案,其中的想法是我可以检测到这些卡住的工作,因为它们的触发器在过去具有nextFiretime。然后,我尝试通过中断它们来阻止这些线程。但是,中断似乎不起作用,线程仍在运行,而nextFiretime不会更新。 我该如何正确打断它们?

工作代码:

protected AtomicReference<Thread> runningThread = null;

/*
 * (non-Javadoc)
 * 
 * @see org.quartz.Job#execute(org.quartz.JobExecutionContext)
 */
@Override
public void execute(JobExecutionContext context)
        throws JobExecutionException
{
    runningThread = new AtomicReference<Thread>();
    try {
        this.runningThread.set(Thread.currentThread());
    } finally { 
        runningThread.set(null); 
    }
}

/*
 * (non-Javadoc)
 * 
 * @see org.quartz.InterruptableJob#interrupt()
 */
@Override
public void interrupt() throws UnableToInterruptJobException
{
    Thread thread = runningThread.getAndSet(null);
    if (thread != null)
        thread.interrupt();
}

用于中断的实际jobcheduler代码:

public int interruptLongRunningJobs(int ms) {
    int jobsInterrupted = 0;
    String jobsInterruptedList = "";

    Date limitInThePast = new Date(System.currentTimeMillis() - ms);

    Scheduler scheduler = this.getJobScheduler();
    // All scheduled jobs
    try {
        for (String groupName : scheduler.getJobGroupNames()) {
            for (JobKey jobKey : scheduler.getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
                JobDetail jobDetail = scheduler.getJobDetail(jobKey);
                final List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);

                Date nextFireTime = null;
                if (triggers.size() > 0)
                {
                    nextFireTime = triggers.get(0).getNextFireTime();

                    if(nextFireTime != null) {
                        if(nextFireTime.before(limitInThePast)) {
                            String jobString = jobDetail.getKey() + "@" + jobDetail.getJobClass().getSimpleName();
                            logger.debug("JobScheduler::interruptLongRunningJobs interrupting: " + jobString);

                            scheduler.interrupt(jobDetail.getKey());

                            if(!jobsInterruptedList.isEmpty()) {
                                jobsInterruptedList += ", ";
                            }
                            jobsInterruptedList += jobString;
                            ++jobsInterrupted;
                        }
                    }
                }
            }
        }
    } catch (SchedulerException e) {
        logger.debug("JobScheduler::interruptLongRunningJobs failed: " + e.getMessage());
    }

    if(jobsInterrupted>0) {
        logger.debug("JobScheduler::interruptLongRunningJobs interrupted jobs#= " + jobsInterrupted);

        emailSomething("JobScheduler::interruptLongRunningJobs interrupted jobs#= " + jobsInterrupted, 
                "These jobs have been interrupted and canceled because they exceeded the maximum running time as detected by triggers with nextFireTime in the past:\r\n" +  
                jobsInterruptedList
        );
    }
    return jobsInterrupted;
}

1 个答案:

答案 0 :(得分:0)

问题是我实现(复制粘贴)public void execute中仅在某些子类中找到的逻辑,这些子类当时处于焦点。我更改了public void execute的代码,以便所有子类都可以轻松使用逻辑。

@Override
public void execute(JobExecutionContext context)
        throws JobExecutionException
{
    runningThread = new AtomicReference<Thread>();
    try {
        this.runningThread.set(Thread.currentThread());
        reallyExecute(context);
    } finally { 
        runningThread.set(null); 
    }
}