SpringBoot定时任务功能怎么实现(springboot,开发技术)

时间:2024-05-05 16:52:56 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

    SpringBoot%E5%AE%9A%E6%97%B6%E4%BB%BB%E5%8A%A1%E5%8A%9F%E8%83%BD%E6%80%8E%E4%B9%88%E5%AE%9E%E7%8E%B0

项目中需要一个可以动态新增定时定时任务的功能,现在项目中使用的是xxl-job定时任务调度系统,但是经过一番对xxl-job功能的了解,发现xxl-job对项目动态新增定时任务,动态删除定时任务的支持并不是那么好,所以需要自己手动实现一个定时任务的功能

1 技术选择

Timer or ScheduledExecutorService

这两个都能实现定时任务调度,先看下Timer的定时任务调度

在看下ScheduledThreadPoolExecutor的实现

两个都能实现定时任务,那他们的区别呢,使用阿里p3c会给出建议和区别

从建议上来看,是一定要选择ScheduledExecutorService了,我们看看源码看看为什么Timer出现问题会终止执行

新建对象时,我们看到开启了一个线程,那么这个线程在做什么呢?一起看看

我们看到,执行了 mainLoop(),里面是 while (true)方法无限循环,获取程序中任务对象中的时间和当前时间比对,相同就执行,但是一旦报错,就会进入finally中清除掉所有任务信息。

这时候我们已经找到了答案,timer是在被实例化后,启动一个线程,不间断的循环匹配,来执行任务,他是单线程的,一旦报错,线程就终止了,所以不会执行后续的任务,而ScheduledThreadPoolExecutor是多线程执行的,就算其中有一个任务报错了,并不影响其他线程的执行。

2 使用ScheduledThreadPoolExecutor

从上面看,使用ScheduledThreadPoolExecutor还是比较简单的,但是我们要实现的更优雅一些,所以选择 TaskScheduler来实现

TaskScheduler是本次功能实现的核心类,但是他是一个接口

前面的代码可以看到,我们在类中注入了这个类,但是他是接口,我们怎么知道是那个实现类呢,以往出现这种情况要在类上面加@Primany或者@Quality来执行实现的类,但是我们看到我的注入上并没有标记,因为是通过另一种方式实现的

在spring初始化时就注册了Bean TaskScheduler,而我们可以看到他的实现是ThreadPoolTaskScheduler,在网上的资料中有人说ThreadPoolTaskScheduler是TaskScheduler的默认实现类,其实不是,还是需要我们去指定,而这种方式,当我们想替换实现时,只需要修改配置类就行了,很灵活。

而为什么说他是更优雅的实现方式呢,因为他的核心也是通过ScheduledThreadPoolExecutor来实现的

这次的实现过程中,我并没有选择xxl-job来进行实现,而是采用了TaskScheduler来实现,这也产生了一个问题,xxl-job是分布式的程序调度系统,当想要执行定时任务的应用使用xxl-job时,无论应用程序中部署多少个节点,xxl-job只会选择其中一个节点作为定时任务执行的节点,从而不会产生定时任务在不同节点上同时执行,导致重复执行问题,而使用TaskScheduler来实现,就要考虑多节点重复执行问题。当然既然有问题,就有解决方案

· 方案一 将定时任务功能拆出来单独部署,且只部署一个节点 · 方案二 使用redis setNx的形式,保证同一时间只有一个任务在执行

我选择的是方案二来执行,当然还有一些方式也能保证不重复执行,这里就不多说了,一下是我的实现

本文:SpringBoot定时任务功能怎么实现的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:C++类和对象之封装及class与struct的区别是什么下一篇:

16 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18