如何通过覆盖来自InterruptableJob接口的中断方法来终止当前正在运行的石英作业?

问题描述 投票:2回答:1

我有一些石英作业来处理一些数据。我在写这些作业时使用了InterruptableJob接口。我必须给这些作业添加一个中断功能。当用户按下终止按钮时,调用这个方法。

@Override
protected void immediatelyTerminate() {

    try {

        String fireInstanceIdToKillJob = "";

        Scheduler scheduler = schedulerFactory.getScheduler();
        List<JobExecutionContext> currentlyExecutingJobs = scheduler.getCurrentlyExecutingJobs();

        for(JobExecutionContext jec : currentlyExecutingJobs) {
            if(jec.getJobDetail().getKey().getName().contains(specificJobKey) {
                fireInstanceIdToKillJob = jec.getFireInstanceId();
            }
        }

        scheduler.interrupt(fireInstanceIdToKillJob);

    } catch (Exception e) {
        logger.debug("error in immediatelyTerminate() method:" + e);
    }
}

调度器.interrupt调用interrupt()方法,这个方法在一个类中被重写,而这个类也有执行方法。有重载中断方法的类是这样的。

private Thread threadToKill;

@Override
public void execute() {
  threadToKill = Thread.currentThread();
}

@Override
public void interrupt() throws UnableToInterruptJobException {
    try {
        threadToKill.interrupt();
    } catch (Exception e) {
        System.out.println("Exception handled "+e);
    }   
}

但这段代码并没有终止工作,而是继续工作 threadToKill.interrupt(); 这一行并没有真正终止运行中的工作。

如何终止正在运行的作业?

java quartz-scheduler jobs
1个回答
0
投票

几年前,我就实现了这个非常相同的功能。

中断一个线程不会杀死它,也不会停止它。. 它只是激活了一个标志,让线程知道它已经被 来停止。大多数内部方法会检查这一点,并抛出一个 InterruptedException 让你去捕捉它,但有些线程会很乐意忽略任何中断请求。所以,要靠作业本身来检测这种情况并采取相应的行动。

基本上,你的 interrupt() 方法应该设置一些标志到 true而你的工作应该不时地检查这个标志,当它注意到这个标志处于活动状态时,就停止它正在做的事情。这就是我如何实现它。

public clas SomeJob implements InterruptableJob {

    protected AtomicBoolean stopFlag = new AtomicBoolean(false);

    @Override
    public void execute(final JobExecutionContext context) {
        for (Item item : listOfItems) { // whatever long tasks(s) you are doing,
            if (stopFlag.get()) {       // just check for this on every main loop
                logger.error("Job interrupted! Leaving at item: "+item);
                break;
            }
            performTask(item);
        }
        cleanUp();
        return;
    }

    private void performTask(Item item) {
        for(....) {               // another loop,
            if (stopFlag.get()) { // another check
                // ....
                return; // or break, depending on each case
            }
            someInternalProcessing(...);
        }
    }

    @Override
    protected void interrupt() {
        stopFlag.set(true);
    }
}

就是这样 只要确保在中止之前清理、关闭连接等。

© www.soinside.com 2019 - 2024. All rights reserved.