Quartz教程三--Job与JobDetail介绍

最新推荐文章于 2025-05-31 21:01:19 发布
神殇彡 最新推荐文章于 2025-05-31 21:01:19 发布
阅读量898 收藏 1
点赞数
分类专栏: Quartz 文章标签: Quartz
Quartz 专栏收录该内容
9 篇文章
订阅专栏

目录
0. Quartz教程–快速入门
1. Quartz教程一–使用Quartz
2. Quartz教程二–API、Job与Trigger
3. Quartz教程三–Job与JobDetail介绍
4. Quartz教程四–Trigger介绍
5. Quartz教程五–SimpleTrigger
6. Quartz教程六–CronTrigger
7. Quartz教程七–TriggerListener和JobListener
8. Quartz教程八–SchedulerListener

正如在教程二中讲到的,Job实现起来很容易,该接口只有一个“execute”方法。本节主要关注:Job的特点、Job接口的execute方法以及JobDetail。

你定义了一个实现Job接口的类,这个类仅仅表明该job需要完成什么类型的任务,除此之外,Quartz还需要知道该Job实例所包含的属性;这将由JobDetail类来完成。

JobDetail实例是通过JobBuilder类创建的,导入该类下的所有静态方法,会让你编码时有DSL的感觉:

import static org.quartz.JobBuilder.*;

让我们先看看Job的特征(nature)以及Job实例的生命期。不妨先回头看看教程一中的代码片段:

// define the job and tie it to our HelloJob class
JobDetail job = newJob(HelloJob.class)
    .withIdentity("myJob", "group1") // name "myJob", group "group1"
    .build();

// Trigger the job to run now, and then every 40 seconds
Trigger trigger = newTrigger()
    .withIdentity("myTrigger", "group1")
    .startNow()
    .withSchedule(simpleSchedule()
        .withIntervalInSeconds(40)
        .repeatForever())            
    .build();

// Tell quartz to schedule the job using our trigger
sched.scheduleJob(job, trigger);

“HelloJob”类可以如下定义:

public class HelloJob implements Job {

    public HelloJob() {
    }

    public void execute(JobExecutionContext context)
        throws JobExecutionException
    {
        System.err.println("Hello!  HelloJob is executing.");
    }
}

可以看到,我们传给scheduler一个JobDetail实例,因为我们在创建JobDetail时,将要执行的job的类名传给了JobDetail,所以scheduler就知道了要执行何种类型的job;每次当scheduler执行job时,在调用其execute(…)方法之前会创建该类的一个新的实例;执行完毕,对该实例的引用就被丢弃了,实例会被垃圾回收;这种执行策略带来的一个后果是,job必须有一个无参的构造函数(当使用默认的JobFactory时);另一个后果是,在job类中,不应该定义有状态的数据属性,因为在job的多次执行中,这些属性的值不会保留。

那么如何给job实例增加属性或配置呢?如何在job的多次执行中,跟踪job的状态呢?答案就是:JobDataMap,JobDetail对象的一部分。

JobDataMap

JobDataMap中可以包含不限量的(序列化的)数据对象,在job实例执行的时候,可以使用其中的数据;JobDataMap是Java Map接口的一个实现,额外增加了一些便于存取基本类型的数据的方法。

将job加入到scheduler之前,在构建JobDetail时,可以将数据放入JobDataMap,如下示例:

JobDetail job = newJob(DumbJob.class)
    .withIdentity("myJob", "group1") // name "myJob", group "group1"
    .usingJobData("jobSays", "Hello World!")
    .usingJobData("myFloatValue", 3.141f)
    .build();

在job的执行过程中,可以从JobDataMap中取出数据,如下示例:

public class DumbJob implements Job {

    public DumbJob() {
    }

    public void execute(JobExecutionContext context)
        throws JobExecutionException
    {
        JobKey key = context.getJobDetail().getKey();

        JobDataMap dataMap = context.getJobDetail().getJobDataMap();

        String jobSays = dataMap.getString("jobSays");
        float myFloatValue = dataMap.getFloat("myFloatValue");

        System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
    }
}

如果你使用的是持久化的存储机制(本教程的JobStore部分会讲到),在决定JobDataMap中存放什么数据的时候需要小心,因为JobDataMap中存储的对象都会被序列化,因此很可能会导致类的版本不一致的问题;Java的标准类型都很安全,如果你已经有了一个类的序列化后的实例,某个时候,别人修改了该类的定义,此时你需要确保对类的修改没有破坏兼容性;更多细节,参考现实中的序列化问题。另外,你也可以配置JDBC-JobStore和JobDataMap,使得map中仅允许存储基本类型和String类型的数据,这样可以避免后续的序列化问题。

如果你在job类中,为JobDataMap中存储的数据的key增加set方法(如在上面示例中,增加setJobSays(String val)方法),那么Quartz的默认JobFactory实现在job被实例化的时候会自动调用这些set方法,这样你就不需要在execute()方法中显式地从map中取数据了。

在Job执行时,JobExecutionContext中的JobDataMap为我们提供了很多的便利。它是JobDetail中的JobDataMap和Trigger中的JobDataMap的并集,但是如果存在相同的数据,则后者会覆盖前者的值。

下面的示例,在job执行时,从JobExecutionContext中获取合并后的JobDataMap:

public class DumbJob implements Job {

   public DumbJob() {
   }

   public void execute(JobExecutionContext context)
        throws JobExecutionException
   {
      JobKey key = context.getJobDetail().getKey();

      JobDataMap dataMap = context.getMergedJobDataMap();  // Note the difference from the previous example

      String jobSays = dataMap.getString("jobSays");
      float myFloatValue = dataMap.getFloat("myFloatValue");
      ArrayList state = (ArrayList)dataMap.get("myStateData");
      state.add(new Date());

      System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
   }
}

如果你希望使用JobFactory实现数据的自动“注入”,则示例代码为:

public class DumbJob implements Job {

   String jobSays;
   float myFloatValue;
   ArrayList state;

    public DumbJob() {
    }

   public void execute(JobExecutionContext context)
        throws JobExecutionException
   {
       JobKey key = context.getJobDetail().getKey();

       JobDataMap dataMap = context.getMergedJobDataMap();  // Note the difference from the previous example

       state.add(new Date());

       System.err.println("Instance " + key + " of DumbJob says: " + jobSays + ", and val is: " + myFloatValue);
   }

   public void setJobSays(String jobSays) {
       this.jobSays = jobSays;
   }

   public void setMyFloatValue(float myFloatValue) {
       myFloatValue = myFloatValue;
   }

   public void setState(ArrayList state) {
       state = state;
   }

}

你也许发现,整体上看代码更多了,但是execute()方法中的代码更简洁了。而且,虽然代码更多了,但如果你的IDE可以自动生成setter方法,你就不需要写代码调用相应的方法从JobDataMap中获取数据了,所以你实际需要编写的代码更少了。当前,如何选择,由你决定。

Job实例

很多用户对于Job实例到底由什么构成感到很迷惑。我们在这里解释一下,并在接下来的小节介绍job状态和并发。

你可以只创建一个job类,然后创建多个与该job关联的JobDetail实例,每一个实例都有自己的属性集和JobDataMap,最后,将所有的实例都加到scheduler中。

比如,你创建了一个实现Job接口的类“SalesReportJob”。该job需要一个参数(通过JobdataMap传入),表示负责该销售报告的销售员的名字。因此,你可以创建该job的多个实例(JobDetail),比如“SalesReportForJoe”、“SalesReportForMike”,将“joe”和“mike”作为JobDataMap的数据传给对应的job实例。

当一个trigger被触发时,与之关联的JobDetail实例会被加载,JobDetail引用的job类通过配置在Scheduler上的JobFactory进行初始化。默认的JobFactory实现,仅仅是调用job类的newInstance()方法,然后尝试调用JobDataMap中的key的setter方法。你也可以创建自己的JobFactory实现,比如让你的IOC或DI容器可以创建/初始化job实例。

在Quartz的描述语言中,我们将保存后的JobDetail称为“job定义”或者“JobDetail实例”,将一个正在执行的job称为“job实例”或者“job定义的实例”。当我们使用“job”时,一般指代的是job定义,或者JobDetail;当我们提到实现Job接口的类时,通常使用“job类”。

Job状态与并发

关于job的状态数据(即JobDataMap)和并发性,还有一些地方需要注意。在job类上可以加入一些注解,这些注解会影响job的状态和并发性。

@DisallowConcurrentExecution:将该注解加到job类上,告诉Quartz不要并发地执行同一个job定义(这里指特定的job类)的多个实例。请注意这里的用词。拿前一小节的例子来说,如果“SalesReportJob”类上有该注解,则同一时刻仅允许执行一个“SalesReportForJoe”实例,但可以并发地执行“SalesReportForMike”类的一个实例。所以该限制是针对JobDetail的,而不是job类的。但是我们认为(在设计Quartz的时候)应该将该注解放在job类上,因为job类的改变经常会导致其行为发生变化。

@PersistJobDataAfterExecution:将该注解加在job类上,告诉Quartz在成功执行了job类的execute方法后(没有发生任何异常),更新JobDetail中JobDataMap的数据,使得该job(即JobDetail)在下一次执行的时候,JobDataMap中是更新后的数据,而不是更新前的旧数据。和 @DisallowConcurrentExecution注解一样,尽管注解是加在job类上的,但其限制作用是针对job实例的,而不是job类的。由job类来承载注解,是因为job类的内容经常会影响其行为状态(比如,job类的execute方法需要显式地“理解”其”状态“)。

如果你使用了@PersistJobDataAfterExecution注解,我们强烈建议你同时使用@DisallowConcurrentExecution注解,因为当同一个job(JobDetail)的两个实例被并发执行时,由于竞争,JobDataMap中存储的数据很可能是不确定的。

Job的其它特性

通过JobDetail对象,可以给job实例配置的其它属性有:

  • Durability:如果一个job是非持久的,当没有活跃的trigger与之关联的时候,会被自动地从scheduler中删除。也就是说,非持久的job的生命期是由trigger的存在与否决定的;
  • RequestsRecovery:如果一个job是可恢复的,并且在其执行的时候,scheduler发生硬关闭(hard shutdown)(比如运行的进程崩溃了,或者关机了),则当scheduler重新启动的时候,该job会被重新执行。此时,该job的JobExecutionContext.isRecovering() 返回true。

JobExecutionException

最后,是关于Job.execute(..)方法的一些额外细节。execute方法中仅允许抛出一种类型的异常(包括RuntimeExceptions),即JobExecutionException。因此,你应该将execute方法中的所有内容都放到一个”try-catch”块中。你也应该花点时间看看JobExecutionException的文档,因为你的job可以使用该异常告诉scheduler,你希望如何来处理发生的异常。

参考

  • Lesson 3: More About Jobs and Job Details

转载地址 http://nkcoder.xyz/2018/01/20/quartz-tutorial-03-job-jobdetail/
确定要放弃本次机会?
福利倒计时
: :

立减 ¥

普通VIP年卡可用
立即使用
神殇彡
关注 关注
  • 0
    点赞
  • 踩
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
  • 分享
    复制链接
    分享到 QQ
    分享到新浪微博
    扫一扫
  • 举报
    举报
专栏目录
第6篇:深度学习入门——神经网络基础
加入“Super Entity”,与全能开发团队共探AI智能体与数字人项目,开启前沿技术之旅。
03-07 342
神经网络是深度学习的基础,广泛应用于各种复杂任务。通过TensorFlow和Keras,我们可以轻松搭建和训练神经网络模型,并通过调整模型结构和参数来优化性能。数据预处理、激活函数选择和正则化是提升模型性能的关键。希望本文的代码示例和注意事项能帮助你更好地理解和应用神经网络。接下来,我们将深入探讨卷积神经网络(CNN)及其在图像识别中的应用。
信息系统项目管理师第四版知识摘编:第2章 信息技术发展
Programming Talk
03-22 2413
当前,深度学习技术是自然语言处理的重要技术支撑,在自然语言处理中需应用深度学习模型,如卷积神经网络、循环神经网络等,通过对生成的词向狱进行学习,以宪成自然语言分类、理解的过程。从区块链的技术体系视角看,区块链基于底层的数据基础处理、管理和存储技术,以区块数据的管理、链式结构的数据、数字签名、哈希函数、默克尔树、非对称加密等,通过基于P2P网络的对称式网络,组织节点参与数据的传播和验证,每个节点均会承担网络路由、验证区块数据、传播区块数据、记录交易数据、发现新节点等功能,包含传播机制和验证机制。
参与评论 您还未登录,请先 登录 后发表或查看评论
【计算机视觉】最全语义分割模型总结(从FCN到deeplabv3+)
热门推荐
wzk4869的博客
03-22 2万+
【计算机视觉】最全语义分割模型总结(从FCN到deeplabv3+)
语义分割技术及其实现
m0_68894275的博客
01-26 1023
这种像素级别的分类能力,使得语义分割在众多领域展现出巨大的应用潜力,从医疗影像诊断到智能交通系统,从机器人导航到虚拟现实,语义分割正逐渐成为推动这些领域发展的关键技术。U-Net通过下采样和上采样的过程,逐步提取图像的特征,并在上采样阶段将这些特征映射回原始图像的分辨率,从而实现精确的分割。在训练过程中,我们需要不断调整模型的参数,优化训练策略,以提高模型的性能。例如,如何提高模型在复杂场景下的分割精度,如何减少模型的计算量,如何更好地处理类别不平衡等问题,都是未来需要进一步研究的方向。
引领弱监督语义分割新潮流:CLIP的强大变身——CLIP-ES
gitblog_00060的博客
06-18 841
引领弱监督语义分割新潮流:CLIP的强大变身——CLIP-ES CLIP-ES 项目地址: https://gitcode.com/gh_mirrors/cl/CLIP-ES 项目介绍 在计算机视觉的领域里...
探索未来视觉技术的钥匙——Awesome Masked Autoencoders深度解析与应用探索
gitblog_00033的博客
06-26 378
探索未来视觉技术的钥匙——Awesome Masked Autoencoders深度解析与应用探索 Awesome-Masked-AutoencodersA collection of literature after or concurrent with Masked Autoencoder (MAE) (Kaiming He el al.).项目地址:https://gitcode.com/...
引领深度学习潮流,刷屏计算机视觉顶会,揭秘商汤研究梦之队
喜欢打酱油的老鸟
11-08 801
机器之心报道 作者:李泽南 57 篇论文入选 ICCV,13 项赛事夺冠。在成为 AI 领军企业的同时,商汤也在为全球学术界作着自己的贡献。 昨天于韩国首尔正式开幕的计算机视觉顶会 ICCV 2019 上,人工智能平台公司商汤科技展示了自己的科研实力:共有 57 篇论文被大会收录,是本届大会上全球论文接收最多的机构。 在计算机视觉(Computer Vision)这个人工智能最为热门的...
探索FFB6D:引领6D姿态估计的新潮流
gitblog_00124的博客
08-16 595
探索FFB6D:引领6D姿态估计的新潮流 项目地址:https://gitcode.com/gh_mirrors/ff/FFB6D 在计算机视觉的众多领域中,6D姿态估计是一项关键技术,广泛应用于机器人导航、增强现实和自动驾驶等领域。今天,我们将深入探讨一款在CVPR2021上获得口头报告殊荣的开源项目——FFB6D,它以其独特的双向融合网络架构,为6D姿态估计领域带来了革命性的进步。 项目介绍 ...
探索视觉表征的无限可能 —— 邀您加入EVA开源项目之旅
gitblog_00921的博客
08-12 356
???? 探索视觉表征的无限可能 —— 邀您加入EVA开源项目之旅 EVAEVA Series: Visual Representation Fantasies from BAAI项目地址:https://gitcode.com/gh_mirrors/ev/EVA 在深度学习领域,视觉表示学习一直是研究的热点。近年来,自监督学习和多模态学习的发展引领了新的潮流,而在这股浪潮中,来自北京智源人工智能研究...
揭秘AI魔法绘画:Stable Diffusion引领无限创意新纪元
程序边界
12-06 8109
本书以实际操作为导向,详细讲解基于Stable Diffusion进行AI绘画的完整学习路线,包括绘画技巧、图片生成、提示词编写、ControlNet插件、模型训练等,同时搭配了丰富的实际操作案例,在附录中还提供了常用提示词中英文对照表,涉及画质、环境、风格、人物、发型、表情、表情符号、眼睛、服装、裤袜与腿饰、鞋子、其他装饰和动作。整本书内容全面、详尽且深入浅出,实用性很强。本书总计8章。
探索未来影像分割:SemTorch深度学习框架
gitblog_00049的博客
06-09 296
探索未来影像分割:SemTorch深度学习框架 去发现同类优质开源项目:https://gitcode.com/ 在计算机视觉领域,图像分割是解决复杂任务的关键技术之一。它能够将图像中的每个像素精准地分配到特定的类别中,从而提供对图像内容的详细理解。现在,我们向您隆重推荐一个强大的开源项目——SemTorch,这是一款基于PyTorch和FastAI 2实现的深度学习图像分割库。 项目介绍 Sem...
语义分割和指称分割
03-24
3. AR/VR环境中虚拟物件放置指导服务优化体验流程效率更高成本更低风险减少收益增加竞争优势明显脱颖而出成为行业标杆引领潮流方向发展未来无限可能性等待探索发现惊喜不断! ```python import torch from ...
进入AI领域做产品 —— 我的自学之路
07-03 1万+
做产品经理这份工作将涉及大量选择,本质上,是需要“输入→内视→输出”的环节更多,所以为了更好的去进行“输出”,学习“输入”(AI基础认知、产品认知、技术通识)以及“内视”(认知框架)的重要性就不言而喻了。 所以,这份内容是关于一个要进入AI领域的产品经理,所需要积累的“输入”的归纳,以及搭建“内视”框架的过程。(第二份输出也已经完成——《出行服务 + AI —— 一次模拟的创业》)
MPEG4视频编码技术介绍
优快云明星博主,认证博客专家,视频、Matlab领域优质创作者。
03-29 3373
MPEG全称是Moving Pictures Experts Group,它是“动态图象专家组”的英文缩写,该专家组成立于1988年,致力于运动图像及其伴音的压缩编码标准化工作,原先他们打算开发MPEG1、 MPEG2、MPEG3和MPEG4四个版本,以适用于不同带宽和数字影像质量的要求。 目前,MPEG1技术被广泛的应用于VCD,而MPEG2 标准则用于广播电视和DVD等。MPEG3最初是为H
Python 如何让自动驾驶的“眼睛”和“大脑”真正融合?——传感器数据融合的关键技术解析
Echo_Wish
05-28 153
摘要:Python在自动驾驶传感器数据融合中发挥关键作用。不同传感器各有局限,需通过数据融合提升系统稳定性。融合方法分为低级、中级和高级融合,常用技术包括卡尔曼滤波和深度学习。Python代码示例展示了卡尔曼滤波在GPS与IMU数据融合中的应用,以及深度学习模型实现LiDAR与摄像头数据融合。Python凭借高效、可扩展的优势,成为自动驾驶传感器数据融合的重要工具,帮助车辆更准确地感知环境并做出决策。
VectorNet:自动驾驶中的向量魔法
weixin_41544125的博客
05-27 891
VectorNet是一种强大的算法,它通过把交通场景中的对象表示成向量,构建子图,进行全局交互,并实时更新和预测,帮助自动驾驶车辆理解复杂的交通场景。就像一个会思考的大脑,VectorNet让车辆能够看懂周围的一切,确保安全行驶。在未来,随着技术的不断进步,VectorNet有望变得更加智能和高效,为自动驾驶车辆提供更强大的支持。让我们一起期待这个智能算法在未来交通中的精彩表现吧!希望这篇技术博客能帮助你更好地理解VectorNet的工作原理和应用。如果你有任何问题或需要进一步的解释,随时告诉我。
自动驾驶系统研发系列—端到端自动驾驶:愿景、陷阱与现实博弈
最新发布
u013889591的专栏
05-31 242
端到端自动驾驶的技术挑战与工程实践思考 本文从一线从业者视角,深入剖析了端到端自动驾驶技术的真实挑战。文章指出,端到端并非万能方案,而是对系统能力的全面考验。关键难点包括:感知与规划的耦合问题、数据闭环构建、算力资源需求、多模态标注体系等深层工程挑战。特别强调了covariate shift、多模态输出监督、累积误差等"隐形困难"的存在,并提出了更合理的评估指标体系建议。
自动驾驶系列—Monocular 3D Lane Detection for Autonomous Driving
u013889591的专栏
05-31 651
单目视觉3D车道线检测研究综述 本文系统梳理了自动驾驶中单目视觉3D车道线检测的研究进展。作为场景理解的核心任务,3D车道检测因其提供深度、曲率等关键信息,在复杂道路环境下展现出比2D检测更优越的性能。论文首先分析了两大技术路线:传统人工特征方法和基于深度学习的CNN、Transformer及混合架构方法,重点介绍了3D-LaneNet、PersFormer等代表性工作。同时指出当前面临的三大挑战:数据变异性大、计算资源需求高和实时性要求严格。文章还整理了现有数据集,探讨了未解决的技术难题。
用 Python 构建自动驾驶的实时通信系统:让车辆“交流”起来!
Echo_Wish
05-25 259
本文介绍了如何用Python构建自动驾驶的实时通信系统。自动驾驶需要依靠高效的通信架构实现车辆间(V2V)、车与环境(V2X)的数据交换,包括传感器数据、云端决策等。文章解析了自动驾驶通信架构的关键组件,并提供了Python代码示例:使用MQTT协议模拟车辆数据发布和云端数据处理。最后展望了5G、边缘计算、AI预测等未来技术趋势,强调实时通信是自动驾驶安全可靠运行的"神经网络"。通过Python可实现高效、低延迟的自动驾驶数据流系统。
神殇彡

博客等级

码龄15年
11
原创
11
点赞
34
收藏
7
粉丝
关注
私信

热门文章

  • Spring Cloud Gateway 内存溢出解决过程 18470
  • python django 添加前台页面 3031
  • python django模版渲染页面 2327
  • Spring Cloud Data Flow 中文版参考文档 2041
  • python django 工作流程 1584

分类专栏

  • Quartz
    9篇
  • JMS
    2篇
  • Python
    6篇
  • spring cloud
    1篇
  • gateway
    1篇
  • oom
    1篇

展开全部 收起

上一篇:
Quartz教程二--API、Job与Trigger
下一篇:
Quartz教程四--Trigger介绍

最新评论

  • Spring Cloud Gateway 内存溢出解决过程

    寸发不生: 你用的是多少版本

  • Spring Cloud Gateway 内存溢出解决过程

    wangyulingreat: 为啥网上这些答案都一模一样?标点符号都不带改的

  • Spring Cloud Gateway 内存溢出解决过程

    -万里晴空-: 我升级到了 2.3.4,SR8 ,还是有问题

  • Spring Cloud Gateway 内存溢出解决过程

    faith云平台-中间件: 楼主我这里遇到一个问题,正常压测的时候,不管有问题的版本,还是新版本,在压测一段时间,内存都会趋于正常,但是我关掉,jemeter之后,就会上涨,遇到了吗

  • Spring Cloud Gateway 内存溢出解决过程

    洛水流川: 我升级到最新的版本 没这个问题了

最新文章

  • Spring Cloud Gateway 内存溢出解决过程
  • Spring Cloud Data Flow 中文版参考文档
  • Quartz教程八--SchedulerListener
2019年2篇
2018年9篇
2015年2篇
2013年7篇

目录

展开全部

收起

目录

展开全部

收起

上一篇:
Quartz教程二--API、Job与Trigger
下一篇:
Quartz教程四--Trigger介绍

分类专栏

  • Quartz
    9篇
  • JMS
    2篇
  • Python
    6篇
  • spring cloud
    1篇
  • gateway
    1篇
  • oom
    1篇

展开全部 收起

目录

评论
被折叠的  条评论 为什么被折叠? 到【灌水乐园】发言
查看更多评论
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值