SpringBoot官方支持任务调度框架,轻量级用起来也挺香

本文介绍了SpringBoot中定时任务的实现,包括Timer、ScheduledThreadPoolExecutor、Spring Task和Quartz。着重讨论了Spring Task的简单易用性和Quartz的灵活性,提供了Quartz与Spring Boot的整合教程,涉及配置、任务创建和Cron表达式的使用。通过示例展示了如何在项目中实现定时发布文章的功能,最后探讨了Quartz的内部工作原理和线程管理。
摘要由CSDN通过智能技术生成

定时任务的应用场景其实蛮常见的,比如说:

  • 数据备份
  • 订单未支付则自动取消
  • 定时爬取数据
  • 定时推送信息
  • 定时发布文章
  • 等等(想不出来了,只能等等来凑, ,反正只要等的都需要定时,怎么样,这波圆场可以吧)

编程喵 实战项目里需要做一个定时发布文章的功能,一开始我想用 Spring Task,于是研究了一番,发现 Spring Task 用起来确实简单,但对于复杂业务却也无能为力。

于是我就把注意力放到了 Quartz 上面,这是一款老而弥坚的开源任务调度框架。

记得我在 14 年开发大宗期货交易平台的时候就用到了它,每天凌晨定时需要统计一波交易数据,生成日报报表,当时配合 Cron 表达式用的。

可惜后来平台稳定了,新的政策出来了,直接把大宗期货交易灭了。于是我发财的机会也随着破灭了。想想都觉得可惜,哈哈哈。

时光荏苒,Quartz 发展到现在,已经可以和 Spring Boot 项目无缝衔接了,今天我们就来实战一把。

Timer

JDK 1.3 就开始支持的一种定时任务的实现方式。内部通过 TaskQueue 的类来存放定时任务,用起来比较简单,但缺陷比较多,比如说一个 Timer 就会起一个线程,任务多了性能就非常差,再比如说如果执行任务期间某个 TimerTask 耗时比较久,就会影响其他任务的调度。

@Slf4j
public class TimerDemo {
    public static void main(String[] args) {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                log.debug("当前时间{}线程名称{}", DateTime.now(),
                        Thread.currentThread().getName());
            }
        };
        log.debug("当前时间{}线程名称{}", DateTime.now(),
                Thread.currentThread().getName());
        Timer timer = new Timer("TimerDemo");
        timer.schedule(task,1000L);
    }
}

代码跑起来后的日志如下所示:

13:11:45.268 [main] DEBUG top.springtask.TimerDemo - 当前时间2022-04-27 13:11:45线程名称main
13:11:46.280 [TimerDemo] DEBUG top.springtask.TimerDemo - 当前时间2022-04-27 13:11:46线程名称TimerDemo

ScheduledThreadPoolExecutor

JDK 1.5 开始提供的的定时任务,它继承了 ThreadPoolExecutor,实现了 ScheduledExecutorService 接口,所以支持并发场景下的任务执行。同时,优化了 Timer 的缺陷。不过,由于使用了队列来实现定时器,就有出入队列、调整堆等操作,所以定时不是非常非常准确(吹毛求疵)。

@Slf4j
public class ScheduledThreadPoolExecutorDemo {
    public static void main(String[] args) throws InterruptedException {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                log.debug("当前时间{}线程名称{}", DateTime.now(),
                        Thread.currentThread().getName());
            }
        };

        log.debug("当前时间{}线程名称{}", DateTime.now(),
                Thread.currentThread().getName());
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);
        executorService.scheduleAtFixedRate(task, 1000L,1000L, TimeUnit.MILLISECONDS);
        Thread.sleep(1000+1000*4);
        executorService.shutdown();
    }
}

输出结果如下所示:

14:43:41.740 [main] DEBUG top.springtask.ScheduledThreadPoolExecutorDemo - 当前时间2022-04-27 14:43:41线程名称main
14:43:42.752 [pool-1-thread-1] DEBUG top.springtask.ScheduledThreadPoolExecutorDemo - 当前时间2022-04-27 14:43:42线程名称pool-1-thread-1
14:43:43.748 [pool-1-thread-1] DEBUG top.springtask.ScheduledThreadPoolExecutorDemo - 当前时间2022-04-27 14:43:43线程名称pool-1-thread-1
14:43:44.749 [pool-1-thread-2] DEBUG top.springtask.ScheduledThreadPoolExecutorDemo - 当前时间2022-04-27 14:43:44线程名称pool-1-thread-2
14:43:45.749 [pool-1-thread-2] DEBUG top.springtask.ScheduledThreadPoolExecutorDemo - 当前时间2022-04-27 14:43:45线程名称pool-1-thread-2
14:43:46.749 [pool-1-thread-2] DEBUG top.springtask.ScheduledThreadPoolExecutorDemo - 当前时间2022-04-27 14:43:46线程名称pool-1-thread-2

Spring Task

Spring Task 是 Spring 提供的轻量级定时任务工具,也就意味着不需要再添加第三方依赖了,相比其他第三方类库更加方便易用。

好像关于 Spring Task,没有其他废话可说了,我们来直接上手。

第一步,新建配置类 SpringTaskConfig,并添加 @EnableScheduling注解开启 Spring Task。

@Configuration
@EnableScheduling
public class SpringTaskConfig {
}

当然了,也可以不新建这个配置类,直接在主类上添加 @EnableScheduling 注解。

@SpringBootApplication
@EnableScheduling
public class CodingmoreSpringtaskApplication {

	public static void main(String[] args) {
		SpringApplication.run(CodingmoreSpringtaskApplication.class, args);
	}

}

第二步

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值