【问题标题】:Getting job key from job class name in Quartz从 Quartz 中的作业类名称获取作业密钥
【发布时间】:2019-02-08 08:38:33
【问题描述】:

我想删除需要作业密钥的作业。我只知道工作类名称。请建议如何使用作业类名称获得相同的名称。

【问题讨论】:

    标签: java quartz-scheduler quartz


    【解决方案1】:

    如果您遍历调度程序实例的所有作业组,您可以找到此信息。从那里你得到jobKey。使用 jobKey,您可以请求保存类信息的 jobDetail。如果匹配,则返回密钥。

    public JobKey getJobKeyByJobClass (Scheduler scheduler, String className){  
        for (final String group : scheduler.getJobGroupNames()) {
            for (final JobKey jobKey : scheduler.getJobKeys(org.quartz.impl.matchers.GroupMatcher.groupEquals(group))) {
                if(className.equals(scheduler.getJobDetail(jobKey).getJobClass().getName())){
                    return jobKey;
                }                               
            }
        }
        return null;
    }
    

    【讨论】:

    • 我知道工作组名称。但问题是我想避免迭代作业的开销,因为作业数量非常多。
    • 为什么要避免迭代?您是否有数百万个工作,或者您是否需要每秒执行 1000 次此搜索?我认为对于您的情况,这根本没有问题。如果您不确定只是弄乱执行时间;)
    • 我的应用程序可以有任意数量的工作。所以,我无法迭代。但是,我的工作已经在我的应用程序中运行。我只需要在某个时候手动停止它,我所拥有的只是作业的类名。
    • 据我所知,您不能仅仅杀死“正在运行”的作业,因为该作业是在调度程序线程池的线程中执行的。如果您的作业没有实现某些自己的终止逻辑,它将一直运行到执行确定为止。
    【解决方案2】:

    您可以通过多种方式获取JobKey。假设您的 Job 实现是 MyJob 类。

    1. 来自JobExecutionContext。如果你的工作正在执行,你可以

      Scheduler scheduler = schedulerFactory.getScheduler(); 
      JobKey jobKey = null;
      for (JobExecutionContext jobCtx : scheduler.getCurrentlyExecutingJobs()) {
          JobDetail jobDetail = jobCtx.getJobDetail();
          if (MyJob.class.equals(jobDetail.getJobClass())) {
              jobKey = jobDetail.getKey();
              break;
          }
      } 
      

      与流相同

      Scheduler scheduler = schedulerFactory.getScheduler(); 
      Optional<JobDetail> job = scheduler.getCurrentlyExecutingJobs()
                    .stream()
                    .map(JobExecutionContext::getJobDetail)
                    .filter(jobDetail -> MyJob.class.equals(jobDetail.getJobClass()))
                    .findFirst();
      JobKey jobKey = job.isPresent() ? job.get().getKey() : null;
      
    2. 按组名。通常,当您提交新作业以执行时,您会提供组和作业名称。如果你不这样做,那就开始吧,它会让事情变得更容易:)

      Scheduler scheduler = schedulerFactory.getScheduler();
      JobKey jobKey = null;
      for (JobKey jk : scheduler.getJobKeys(GroupMatcher.jobGroupEquals("myGroup"))) {
          if (MyJob.class.equals(scheduler.getJobDetail(jk).getJobClass())) {
              jobKey = jk;
              break; 
          }
      }
      

      与流相同

      Scheduler scheduler = schedulerFactory.getScheduler(); 
      Optional<JobDetail> job = scheduler.getJobKeys(GroupMatcher.jobGroupEquals("myGroup"))
                    .stream()
                    .map(jk -> scheduler.getJobDetail(jk))
                    .filter(jobDetail -> MyJob.class.equals(jobDetail.getJobClass()))
                    .findFirst();
      JobKey jobKey = job.isPresent() ? job.get().getKey() : null;
      

    希望对你有帮助!

    【讨论】:

    • 感谢您的回答。但是有没有办法避免迭代。我的工作已经在我的应用程序中运行,我正试图找到一种方法在某个时间点手动停止它。
    • @BhavyaSharma,这很简单,只需创建包含您要终止的单个作业的组。其他一切都是一样的,您正在按您的组查询 scheduler 的 JobKeys,并且只有目标工作。 :) 你想从它的实现类中终止 Job 吗?
    • 是的,我也想过通过创建单个组来做到这一点。是的,我想从其实现类中终止 Job。
    • @BhavyaSharma,那么您可能可以访问JobExecutionContext。在这种情况下,获取密钥很明显jobExecutionContext.getJobDetail().getKey()
    • 略有变化。我想创建一个 api,它将使用 GUICE 访问我的实现类。我正在考虑将键的值存储到实现类中的某个变量中,然后在其余端点中使用它来完成这项工作。
    猜你喜欢
    • 1970-01-01
    • 2021-07-09
    • 2011-11-15
    • 1970-01-01
    • 2015-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多