【问题标题】:Is it possible to kill a current running Quartz Job?是否可以终止当前正在运行的 Quartz Job?
【发布时间】:2012-10-26 05:43:13
【问题描述】:

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

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

例如:

  1. 作业通过 Hibernate 触发了一个命名 SQL 查询,这需要很长时间
  2. 已调用第三方服务器,第三方服务器需要很长时间才能响应

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

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

【问题讨论】:

    标签: quartz-scheduler


    【解决方案1】:

    您可以创建一个名为 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)
        {
        }
    }
    

    假设使用一些工厂来创建作业

    要停止作业,您将调用方法scheduler.Interrupt(new JobKey(jobName));

    【讨论】:

    • 这看起来正是我所需要的。但是每当我尝试中断工作时,我都会得到异常'ThreadAbortException'。
    • @Schoof 没错。如果您查看Thread.Abort() 的文档,您会发现它引发了ThreadAbortException msdn.microsoft.com/en-us/library/…
    【解决方案2】:

    正如您所说,在石英中没有办法“粗暴地”中断工作,在 JAVA 中也没有。

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

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

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

    希望对你有帮助

    【讨论】:

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

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

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

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

    上面是用来启动job之类的

      scheduler.start();
    

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

     scheduler.shutdown();
    

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

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

    其中 jobDetail 和 simpleTrigger 是不言自明的。

    希望对您有所帮助。 :)

    【讨论】:

    • 这将杀死整个调度程序而不是调度程序中的特定作业
    • 是的,是的。如果调度程序只有一项工作。那么这个方法就可以完美运行了。刚提了个建议。
    猜你喜欢
    • 2019-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-26
    • 2019-05-22
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多