当前位置: 首页 > 科技观察

从零搭建开发脚手架 基于Spring Task实现动态管理任务

时间:2023-03-13 01:34:44 科技观察

从零搭建开发脚手架基于SpringTask实现动态管理任务本文转载请联系Java大厂面试官公众号。什么是定时任务?定时任务是由调度器在指定的时间或周期触发的任务。常见的场景如下:定时发送短信。定期更改数据。定期统计数据。定期修改状态。定期开始活动。Timer简介:Timer是Jdk自带的一个定时任务执行类。任何项目都可以直接使用Timer来实现定时任务,所以Timer的好处就是简单易用。原理:调度器:单线程。任务存储:最小堆实现任务存储。优点:Jdk自带类,无需引入其他Jar,简单易用。缺点:Timer中的多个任务只能使用一个线程来执行,所以任务的执行会相互影响。当一个任务的执行时间过长时,会影响其他任务的调度。任务异常影响其他任务。当一个任务抛出异常时,其他任务也会终止。结论:基本不用。ScheduledExecutorService简介:ScheduledExecutorService是JDK中的几个自定义线程池之一。支持多线程并发执行多个调度任务,弥补了Timer的缺陷。原理:调度器:多线程。任务存储:最小堆实现任务存储。优点:ScheduledExecutorService可以做到Timer能做到的一切,完美解决了上面提到的Timer的两个问题。缺点:只支持固定速率或固定延迟的调度任务,不灵活。结论:常用于框架内部的定时任务。SpringTask说明:Spring框架自带的定时任务。优点:与ScheduledExecutorService相同,但也支持cron表达式,可以配置任何基于时钟的调度任务。缺点:不支持动态修改任务状态、挂起/恢复任务、终止正在运行的任务。不支持在线监控已执行的任务。原理:ScheduledExecutorService的扩展。总结:在中小企业中经常作为单机定时任务使用。以上均为单机版。其他分布式定时任务如:quartz、xxl-job、elastic-job等,功能和性能都非常强大,这里不作为研究对象。具体可以参考:Java定时任务框架比较定时任务实现原理最小堆时间轮这些框架都不是我想选的。如果你想自由操控Thunderbolt,你可以自己造一个简单的轮子来满足90%的需求。有望实现以下特点:重量轻、重量轻、重量轻。支持在线监控已执行的任务。支持动态修改任务状态、暂停/恢复任务、终止正在运行的任务。支持在线配置调度任务入参。支持集群环境扩展(可选)。搜了半天资料,直接用SpringTask实现就可以了,只需要依赖SpringBoot。SpringTask详解初级静态配置任务代码示例:@Component@EnableScheduling//启用定时任务publicclassDemoApplication{//添加定时任务@Scheduled(cron="0/5*****")//cron表达式,每5执行publicvoiddoTask(){System.out.println("我是定时任务~");}}不能动态修改任务状态,暂停/恢复任务,终止正在运行的任务。高级动态配置任务设计的关键技术点和陷阱SpringTask默认的调度器是线程数为1的ThreadPoolTask??Scheduler,自动组装类是TaskSchedulingAutoConfiguration。多个任务的执行会相互影响,所以必须修改默认值。通过TaskScheduler接口,可以扩展动态修改任务状态、挂起/恢复任务、终止正在运行的任务。TaskScheuler是Spring3.0引入的,有多个方法可以在未来的某个时间点运行,它也返回一个ScheduledFuture接口的对象,可以用来取消一个定时任务或者检查一个任务是否完成。cron-utils是一个用于解析和验证Cron表达式的Java库。你可以去GitHub查看详细说明。实现设计定义了IJob接口,用于描述客户端的任务。publicinterfaceIJob{voidexecute(JobContextmap)throwsJobException;}定义了注解,用于结合IJob接口定义任务。@Target({ElementType.TYPE})@Retention(RetentionPolicy.RUNTIME)@Documented@Componentpublic@interfaceJob{@AliasFor(annotation=Component.class)Stringvalue()default"";/***cron表达式不默认为"-》表示不执行*/Stringcron()default"-";/***任务代码必须唯一*/StringtaskCode();/***任务名称*/StringtaskName();}定义任务运行状态publicclassTask{/***任务的代码必须全局唯一*/privateStringtaskCode;/***任务名称*/privateStringtaskName;/***任务类名*/privateStringtaskClassName;/***任务cron表达式*/privateStringtaskCron;@JsonIgnoreprivateScheduledFuturescheduledFuture;@JsonIgnoreprivateIJobjob;privateTaskStateEnumtaskState;定义存储在缓存或DB中的任务存储接口publicinterfaceITaskStoreskfindByTaskCode(StringtaskCode);}定义任务锁接口,解决并发问题,扩展对集群环境,各种回调等的支持publicinterfaceIEventListener{voidlistener(Eventevent);}核心处理器,处理核心进程初始化加载所有IJob实现获取IJob从Spring容器实现类并解析Job注解添加任务threadPoolTask??Scheduler.schedule(task,cron)更新任务详情scheduledFuture.cancel(true)threadPoolTask??Scheduler.schedule(task,cron)启动任务threadPoolTask??Scheduler.scheduler(task,cron)暂停任务scheduledFuture.cancel(true)taskmonitorTaskListfunctiontobeimplementedretrycompensation:failretryfailstore:storefailedtask,用于人肉补偿。misfire:存储错过的任务以供人为补偿。您可以自行在核心处理器中添加相应的增强功能逻辑。使用例子直接实现IJob接口并添加Job注解@Job(taskCode="job1",taskName="lakertesttask",cron="0/5*****")@Slf4jpublicclassTestJobimplementsIJob{@Overridepublicvoidexecute(mapmap)throwsException{log.info("lakerjobrun");TimeUnit.SECONDS.sleep(10);}}完整代码:https://gitee.com/lakernote/lakernote参考:https://juejin.cn/post/6844904002606350343SpringBoot官网