问题 是否有可能杀死当前正在运行的Quartz Job?


我记得我们不能杀死当前正在运行的Quartz Job,但我们可以打断并在必要时进行布尔检查,无论我们是否需要继续进行后续操作。

即使我们实现InterruptableJob并调用scheduler.interrupt来中断Job,当前执行的作业仍将在服务器中运行。

例如:

  1. 作业通过Hibernate触发了一个命名的SQL查询,这需要很长时间
  2. 已经对第三方服务器进行了呼叫,其中第三方服务器需要很长时间 时间回应

http://neopatel.blogspot.in/2011/05/quartz-stop-job.html http://forums.terracotta.org/forums/posts/list/3191.page

有人可以纠正我的理解并解释我如何杀死或阻止“当前”执行的工作?

谢谢, 本Kathir


10953
2017-10-26 05:43


起源



答案:


正如你所说,在JAVA中,没有办法打断“粗暴”的石英工作。

您可以将作业的逻辑封装在单独的Thread中,并使用ExecutorService运行它。

看看这个例子: https://stackoverflow.com/a/2275596/1517816

假设您的QuartzJob是Test类,并在Task类中移动您的业务逻辑。

希望能帮助到你


3
2017-10-26 07:31



我同意我们不能在JAVA中残酷地杀死Quartz的工作。此外,同意我们可以通过ExecutorService实现相同的目标。出于好奇,它又提出了一个问题,为什么Quartz没有实现ExecutorService,这样他们就可以为我们提供一种杀死工作的方法?或者Quartz增强功能是否有未来的计划。感谢您的澄清,请让我知道您的想法。 - Kathir
为什么它没有实现可能是因为它被设计为提供替代jvm中的这种缺乏。它适用于旧的jvms,如果它们实现ExecutorService,则quartz将与最近的jvm和force项目链接以进行迁移 - poussma
可能他们可以通过配置提供额外的或广泛的支持。通过这种方式,他们可以实现提供向下兼容性以及新的...我错过了什么?..无论如何,谢谢你的时间和解释...... - Kathir
您可以监视套接字并需要终止在线程期间打开的套接字...可以打开套接字以供第三方访问 - Kathir


答案:


正如你所说,在JAVA中,没有办法打断“粗暴”的石英工作。

您可以将作业的逻辑封装在单独的Thread中,并使用ExecutorService运行它。

看看这个例子: https://stackoverflow.com/a/2275596/1517816

假设您的QuartzJob是Test类,并在Task类中移动您的业务逻辑。

希望能帮助到你


3
2017-10-26 07:31



我同意我们不能在JAVA中残酷地杀死Quartz的工作。此外,同意我们可以通过ExecutorService实现相同的目标。出于好奇,它又提出了一个问题,为什么Quartz没有实现ExecutorService,这样他们就可以为我们提供一种杀死工作的方法?或者Quartz增强功能是否有未来的计划。感谢您的澄清,请让我知道您的想法。 - Kathir
为什么它没有实现可能是因为它被设计为提供替代jvm中的这种缺乏。它适用于旧的jvms,如果它们实现ExecutorService,则quartz将与最近的jvm和force项目链接以进行迁移 - poussma
可能他们可以通过配置提供额外的或广泛的支持。通过这种方式,他们可以实现提供向下兼容性以及新的...我错过了什么?..无论如何,谢谢你的时间和解释...... - Kathir
您可以监视套接字并需要终止在线程期间打开的套接字...可以打开套接字以供第三方访问 - Kathir


你可以创建一个名为JobBase的新抽象类,例如实现IJob接口并插入抽象方法: public abstract void ExecuteJob(IJobExecutionContext context);

在JobBase上,您可以像这样实现方法Execute

public abstract class JobBase : IJob,IInterruptableJob
{
     private Thread currentThread;
     private ILog logger;
     public JobBase(ILog logger)
     {
        this.logger=logger;
     }
        public void Execute(IJobExecutionContext context)
        {

            var thread = new Thread(()=> 
            {
                try
                {
                    this.ExecuteJob(context);
                }
                catch(Exception ex)
                {
                    this.logger.ErrorFormat("Unhandled exception {0}",ex.ToString());

                }
            });

            thread.Start();
            this.currentThread = thread;
            this.currentThread.Join();  
        }
        public abstract void ExecuteJob(IJobExecutionContext context);

        public void Interrupt()
        {   
            currentThread.Abort();
        }
}

每个Job都将实现JobExecute方法。

  public class TestJob :JobBase
{
    private ILog logger;
    public TeJob(ILog logger):base(logger)
    {
    }

    public override ExecuteJob(IJobExecutionContext context)
    {
    }
}

假设使用一些工厂来创建一个Job

对于停止工作,您将调用方法 scheduler.Interrupt(new JobKey(jobName));


8
2017-09-02 11:26



这看起来正是我需要的。但每当我试图打断一个工作时,我都会得到exceptoin'ThreadAbortException'。 - Schoof
@Schoof这是正确的。如果你看一下文档 Thread.Abort() 你看到它提出了一个 ThreadAbortException  msdn.microsoft.com/en-us/library/... - Jordy van Eijk


我不知道为什么没有人提到这一点,或者在问到这个问题时可能没有这个。

Scheduler实例有一个名为shutdown的方法。

 SchedulerFactory factory = new StdSchedulerFactor();
 Scheduler scheduler = factory.getScheduler();

以上用于开始像这样的工作

  scheduler.start();

使用标志或其他东西知道何时停止作业运行。然后用

 scheduler.shutdown();

我是如何实现我的要求的:

 if(flag==true)
{
    scheduler.start();
    scheduler.scheduleJob(jobDetail, simpleTrigger);
}
else if(flag==false)
{
    scheduler.shutdown();
}

其中jobDetail和simpleTrigger是自解释的。

希望能帮助到你。 :)


1
2018-05-22 10:47



这将终止整个调度程序而不是调度程序中的特定作业 - Kathir
是的,是的。如果调度程序只有一个作业。然后这种方法将完美地工作。刚给出了一个建议。 - Nikhil Kumar