首页 > 编程知识 正文

不定式的三种形式(java如何设置定时任务)

时间:2023-05-06 10:36:17 阅读:75925 作者:1939

javatechnologystack 2016-10-2211:04大多数系统都会遇到与计划任务相关的功能,如定时备份数据库、定时修改特定信息和自动取消订单30分钟。 许多功能可以基于linux的计划命令来执行。 虽然与特定业务系统密切相关的任务必须在代码中执行,但计划功能实际上有多种实现方式。 如果你的项目是基于spring的,就可以在配置中实现。 或者,也可以使用JDK附带的timer、线程池进行。

首先,让我们简要回顾一下如何使用Timer和“线程池”(ScheduledExecutorService )实现简单的计划任务。 Timer和ScheduledExecutorService都可以用于定时任务,包括延迟执行管理任务(例如1000ms后执行任务)、周期性执行任务(例如每500ms执行任务)。 但是,到了JDK1.5以后,由于以下原因,建议使用后者。

1、对时间表的支持基于绝对时间而不是相对时间,因此任务对系统时钟的变化很敏感; 但是,ScheduledThreadExecutor只支持相对时间。

2、如果TimerTask抛出未检查的异常,Timer会采取意想不到的行动。 由于Timer线程不会捕获异常,因此TimerTask抛出的未检查异常将终止Timer线程。 此时,已调度但尚未运行的TimerTask将永远不再运行,新任务也将无法调度。

3、Timer中的任务如果执行时间太长,就会独占Timer对象,以后的任务总是无法执行。 ScheduledExecutorService不会出现时间问题(除非只创建一个单线程池任务区域)。

让我们看看如何使用Timer和ScheduledExecutorService完成计划任务的创建。

今天我们的主角是Quartz,但这里没有说明关于Quartz的基础知识。 这些知识比较简单,大家可以自己在百度上了解。 这里是官方地址http://www.quartz-scheduler.org/

Quartz是OpenSymphony开源组织Job scheduling领域的另一个开源项目,可以组合使用J2EE和J2SE APP应用程序,也可以单独使用。 Quartz可用于创建简单的程序,也可用于创建运行10个、100个甚至数万个Jobs的复杂程序。 OBS可以是标准Java组件或EJBs。 Quartz的最新版本是Quartz 2.2.3。

使用spring,您可以轻松地在配置中进行日程安排,但也可以获得以下好处:您可以单独部署日程安排服务,或者在日程安排服务中创建中间件,以执行其他任务。 今天不使用spring,只通过quartz看看如何实现任务的调度。

1、服务架构设计

定时服务作为独立的服务运行,与其他系统关系互补,同步和异步调用都是可能的。 设计之初,我打算把它作为异步系统制作。 它只负责任务的日程安排,具体执行是通过调用接口完成的。 另一方面,任务的存储目前是基于内存的。 我们尝试了基于数据库MYSQL的,没有什么大问题,但是配置略有不同。

2、需要考虑的问题

(1)接口设计

一般需要支持registe、delete、update、query等接口。 在此,我们将registe接口定义为demo。

(2)任务参数

其他系统要使用此系统,必须调用registe接口。 必须定义存储任务信息的实体。 某些字段是必填字段。 例如,任务来自哪里,任务属于哪个组,例如订单组、任务类型、任务开始时间、任务结束时间、执行任务时所需的数据,例如订单ID。创建任务后

重点讨论任务参数的任务分类,但在此将任务分为两类。 (1)一次性任务,即执行一次后立即退出并执行第二次(2)公式任务而不循环执行的任务,以及在quartz支持的conf公式中执行的任务,在时间上灵活、可以一次性、循环等。 另外,你可能还怀疑我们为什么要开发这样的接口。 某些任务内置于系统中,并在服务启动时自动注册。 另外,还有有订单才注册等以后发生的任务。 以具体代码为例。

3、实际案例

(1)注册接口定义

(2)容器实例创建

在容器注册这些任务之前,必须启动服务并创建容器实例。 quartz通过SchedulerFactory工厂检索scheduler实例,并调用其start方法完成启动。 启动后,在上下文对象中

中放入一些键值,在任务执行的时候来获取使用。


服务在启动时,加载quartz的调度实例后,调用loadSystemTasks方法,来加载系统级别的任务例如定时备份数据库这个任务,然后再调用loadTaskFromDb方法,去加载数据库中未完成的任务(因为服务停止后,任务并没有被执行,所以等服务启动后要先去加载这些未完成的任务)。

(3)任务保存逻辑

1、保存前,根据参数获取任务的key。

2、首先保存到数据库MYSQL中,防止服务宕机,任务丢失找不回。

3、再保存到quartz容器中,启动该任务。

通过scheduler的schedulerJob方法就可以将任务放置在容器中。

(4)任务实例

quartz容器在接受任务时,需要两个核心的参数(1)jobDetail 任务实例(2)trigger 时间配置;前者的意思是指明本次任务的执行信息,后者说明了这个任务的开始结束时间等。

所以我们设计接口的时候,也需要在调用scheduler.scheduleJob(jobDetail, trigger);的时候,需要传递两个参数,一个是jobDetail,一个是trigger。我们看他们是如何通过代码被创建的,我们进行了封装。

创建JobDetail的时候,我们要关联一个执行类,也就是ExecuteJob,并且告诉任务容器,这个任务唯一的key值,防止任务重复。创建trigger的时候,我们分为一次性任务和表达式任务。他们的构建方式是不同的。

ScheduleBuilder<?> scheduleBuilder = simpleSchedule();

ScheduleBuilder<?> scheduleBuilder = cronSchedule(timeJob.getConf());

表达式任务需要客户端传入一串表达式,而表达式如何写要再单独去学习,例如举个简单例子:0 0/2 * * * ? 每两分钟执行一次。

(5)任务执行类

刚才我们设置了我们的任务执行类ExecuteJob,这个类是说当任务到了时间点就会调用executeJob的某个方法来完成一系列的工作。

ExecuteJob实现了Job接口,重写execute方法,在这个方法里,我们来完成我们的任务,但也有可能我们需要调用外部的接口完成,但有一个问题就是这个任务执行是异步的,和spring容器是独立开来的,不能执行使用spring的实例。有这么几种方式来获取spring的容器实例:

(1)使用ApplicationUtil工具类获取。

(2)使用JobDataMap获取。

(3)使用上下文获取。

(6)quartz配置

Quartz支持基于内存和数据库来存储任务示例,配置如下:

当然,如果你选择基于数据库保存任务,还需要执行自带的一段数据库脚本,这个可以去百度找到。而如果你使用的是基于内存来管理任务,那么你就需要自己设计数据库来存储这些任务的信息了。就我的经验来讲,如果你的系统并发较高,任务较多建议使用基于数据库来存储,如果任务相对少,内存是完全够用的。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。