【技术选型】Java 定时任务
文章目录
- 背景
- 一、基础
- 1.1 Cron表达式
- 1.2 定时任务的三大组成部分
- 二、Java做定时任务的技术方案比较
- 2.1、JDK seelp实现定时任务
- 2.2、JDK Timer & TimerTask 实现定时任务
- 2.3、JDK ScheduledExecutorService
- 2.4、Quartz框架
- 2.5、Spring Task 中的 @schedule
- 2.6、Elastic-Job框架
- 2.7、PowerJob框架
- 2.8、Xxl-job
- 三、共同点和不同点
- 总结
背景
在日常的开发工作中我们经常会遇到定时任务的相关问题,比如:
- 信用卡定时每月给用户推送账单数据;
- 轮训更新某个任务的状态是否完成;
- 设置一个定时提醒;
- 邮件或消息设置定时发送;
- 定时统计某个时间段的数据存入缓存;
等等,定时可以算一个最常用的开发工作,你日常的工作中肯定也写了不少的定时任务代码,但是你真的了解定时任务吗?
下面让我们一起进入定时任务的学习!
一、基础
1.1 Cron表达式
cron是当前做定时任务的基础,即使很多人说cron表达式不容易理解,但这是现在阶段所有程序编写定时任务的基础和唯一选择。
就算做不到熟练编写,也应该做到看到能懂;
Cron表达式是一个字符串,字符串以5或6个空格隔开,分为6或7个域,每一个域代表一个含义;
接下来具体看cron属性对应时间表达式的定义规则:
- 按顺序依次是:秒、分、时、日、月、周,中间用空格间隔
- 月、周可以用数字或英文单词的前三个字母表示
- 日和周可能会冲突,因此两个可以有一个配置为?
- 常用通配符的含义:
*
表示任意值,例如在秒字段上设置*,表示每秒都触发?
表示不指定值,只能出现在日或者周的位置,用于处理日和周可能存在的冲突,例如2020年8月15是周六,如果又在周的位置上指定为周一,那就会产生冲突到导致定时任务失效。如果我们不关心日或者周的时候,也可以将其设置为?
-
表示时间区间,例如在秒上设置1-3,表示第1、2、3秒都会触发/
表示时间间隔,例如在秒上设置2/4,表示从第2秒开始每间隔4秒触发一次,
表示列举多个值,例如MON,WED,FRI表示周一、周三、周五触发
例如:
- 每隔5秒执行一次:*/5 * * * * ?
- 每隔1分钟执行一次:0 */1 * * * ?
- 每天23点执行一次:0 0 23 * * ?
- 每天凌晨1点执行一次:0 0 1 * * ?
- 每月1号凌晨1点执行一次:0 0 1 1 * ?
- 每月最后一天23点执行一次:0 0 23 L * ?
- 每周星期天凌晨1点实行一次:0 0 1 ? * L
- 在26分、29分、33分执行一次:0 26,29,33 * * * ?
- 每天的0点、13点、18点、21点都执行一次:0 0 0,13,18,21 * * ?
1.2 定时任务的三大组成部分
调度器Scheduler、执行器 executors、触发器 Trigger
不管你使用的什么框架、用的是什么系统,或者将来又出现什么新的定时任务技术,都离不开这三部分。
我们以一个闹钟响铃的任务为例:
- 执行器executors:发出一阵刺耳的声音;(具体的执行操作)
- 触发器Trigger:发出声音的具体时间; (触发任务执行的规则,多为时间规则。)
- 调度器Scheduler:一直运行到触发时间点发出刺耳的声音;(进行任务的调度)
所以,当接手一个新的定时任务的框架,首先要看其这三部分是这么去实现的;
二、Java做定时任务的技术方案比较
Java做定时任务的技术方案有多种,本文将比较常见的技术方案,分析它们的优缺点,以便开发人员在实际项目中选择合适的技术方案。
2.1、JDK seelp实现定时任务
- 使用
Thread.sleep()
方法实现定时任务。可以在独立的线程中执行任务,并在每次任务完成后使用Thread.sleep()
方法让线程休眠一段时间。 - 下面是一个示例,该示例定义了一个任务,该任务每隔1秒打印“hello timer”:
public class TimerExample {public static void main(String[] args) { Runnable task = new Runnable() { public void run() { while (true) { System.out.println("hello timer"); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }; Thread thread = new Thread(task); thread.start(); }
}
- 请注意,在本例中,任务是在无限循环中执行的,并且每次任务完成后线程都会休眠1秒。如果想要执行特定次数的定时任务,可以在任务内部使用计数器并在达到特定次数后终止循环。
2.2、JDK Timer & TimerTask 实现定时任务
使用Java的java.util.Timer和java.util.TimerTask类
来创建定时任务。
-
下面是一个简单的例子,其中定义了一个任务,该任务每隔1秒执行一次:
import java.util.Timer; import java.util.TimerTask; public class TimerExample { public static void main(String[] args) { TimerTask task = new TimerTask() { public void run() { System.out.println("Task executed"); } }; Timer timer = new Timer(); long delay = 1000; long interval = 1000; timer.scheduleAtFixedRate(task, delay, interval); } }
-
在上面的代码中,创建了一个
TimerTask
对象,该对象的run
方法定义了要执行的任务。然后,使用Timer类创建了一个定时器,并使用scheduleAtFixedRate
方法指定了任务的执行频率(即每隔1秒执行一次)。请注意,
java.util.Timer
是非线程安全的,因此在多线程环境中使用时需要注意。如果需要更复杂的定时任务,请考虑使用其他库,例如
java.util.concurrent
中的ScheduledExecutorService
。 -
在Java 5之前,它是唯一的定时任务工具,在Java 5之后,JDK提供了更好的替代方案。
-
优点:
- 轻量级,使用简单。
- 可以实现较为简单的定时任务功能。
-
缺点:
- 不支持复杂的定时任务类型,如cron表达式
- 不支持任务持久化
- 在定时任务数量很多的情况下,性能可能存在问题
- 不支持分布式
-
2.3、JDK ScheduledExecutorService
-
ScheduledExecutorService是Java 5新增的一个接口,它位于java.util.concurrent包内,可以通过ThreadPoolExecutor来实现。可以使用它创建和执行定期执行的任务,并且可以控制任务的执行频率。
它可以很方便地实现定时任务,支持多种执行方式,比如单次定时、固定频率定时和固定延迟时间定时等。 -
以下是一个示例,该示例每隔1秒钟打印“hello timer”:
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ScheduledExecutorServiceExample { public static void main(String[] args) { ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); Runnable task = new Runnable() { public void run() { System.out.println("hello timer");} }; executor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS); }
}
-
在本例中,使用
Executors
类的newScheduledThreadPool
方法创建了一个ScheduledExecutorService
对象,并使用该对象的scheduleAtFixedRate
方法将任务安排在每隔1
秒钟执行一次。可以根据需要更改任务的执行频率。 -
优点:
- 简单易用,可灵活配置。
- 支持多种定时任务类型,灵活度高。
- 支持并发调度,可以提高性能。
-
缺点:
- 不支持分布式
- 任务执行结果管理不够方便
2.4、Quartz框架
-
Quartz是一个流行的开源的定时任务框架,支持非常丰富的定时任务类型,比如简单定时任务、复杂定时任务、集群定时任务、任务持久化等。
-
以下是一个使用Quartz创建定时任务的示例:
import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; public class QuartzExample { public static void main(String[] args) throws SchedulerException { JobDetail job = JobBuilder.newJob(HelloJob.class).withIdentity("myJob", "group1").build(); Trigger trigger = TriggerBuilder.newTrigger() .withIdentity("myTrigger", "group1") .startNow() .withSchedule(SimpleScheduleBuilder.simpleSchedule() .withIntervalInSeconds(1) .repeatForever()) .build(); Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler(); scheduler.start();scheduler.scheduleJob(job, trigger); } }public class HelloJob implements Job {public void execute(JobExecutionContext context) {System.out.println("hello timer");} }
-
在本例中,创建了一个名为HelloJob的作业类,该类实现了Quartz的Job接口。
还创建了一个作业详细信息对象和一个触发器对象,并使用触发器安排了每隔1秒钟执行一次的任务。最后,启动了调度程序并使用其scheduleJob方法将任务与触发器关联。 -
优点:
- 功能丰富,支持多种定时任务类型。
- 支持任务持久化,保证任务不会丢失。
- 支持分布式,可以实现任务的高可用和负载均衡。
-
缺点:
- 依赖比较大,使用起来比较复杂。
- 配置较为繁琐,需要考虑集群和持久化等问题。
2.5、Spring Task 中的 @schedule
-
Spring Task是Spring框架提供的一个模块,可以用来进行定时任务的管理。通过@Scheduled注解,可以实现简单的定时任务设置。同时也支持通过cron表达式设置复杂的定时任务。
-
以下是一个示例,该示例每隔1秒钟打印“hello timer”:
import org.springframework.scheduling.annotation.Scheduled; public class ScheduledAnnotationExample { @Scheduled(fixedRate = 1000) public void printMessage() { System.out.println("hello timer"); } }
-
在本例中,使用@Scheduled注解将任务标记为定时任务,并使用fixedRate属性设置任务的执行频率,即每隔1秒钟执行一次。
-
优点:
- 集成简单,开发便捷。
- 支持使用注解来配置定时任务,使得代码更加易读易维护。
-
缺点:
- 不支持分布式
- 不支持任务持久化
2.6、Elastic-Job框架
-
Elastic-Job是一个分布式作业调度框架,提供了高可用性、高扩展性等功能,可以用于创建分布式定时任务。
-
以下是使用Elastic-Job创建一个简单的定时任务的示例:
import com.dangdang.ddframe.job.api.ShardingContext; import com.dangdang.ddframe.job.api.simple.SimpleJob; public class MyJob implements SimpleJob { @Override public void execute(ShardingContext shardingContext) { System.out.println("Hello, world!"); } }
-
在本例中,创建了一个名为MyJob的作业类,该类实现了Elastic-Job的SimpleJob接口。可以在execute方法中编写定时执行的代码。还需要创建一个作业配置文件,该文件配置了任务的定时时间和任务的执行策略。
2.7、PowerJob框架
-
PowerJob是一种使用Java语言编写的分布式任务调度系统,可以用于创建定时任务。
-
以下是使用PowerJob创建一个简单的定时任务的示例:
import com.dangdang.ddframe.job.api.ShardingContext; import com.dangdang.ddframe.job.api.simple.SimpleJob; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyJob implements SimpleJob { private static final Logger logger = LoggerFactory.getLogger(MyJob.class); @Override public void execute(ShardingContext shardingContext) { logger.info("Hello, world!"); } }
-
在本例中,创建了一个名为MyJob的简单作业类,该类实现了PowerJob的SimpleJob接口。可以在execute方法中编写定时执行的代码。
2.8、Xxl-job
-
Xxl-job是一个Java分布式定时任务解决方案,提供了高可用性、高扩展性等功能,可以用于创建分布式定时任务。可以用来代替Quartz。它支持类似cron表达式的定时任务设置,支持多种执行器类型,比如本地任务、Shell任务、Http任务等。同时还支持任务执行结果的管理和调度中心的高可用等特性。
-
以下是使用XXL-JOB创建一个简单的定时任务的示例:
import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.annotation.JobHandler; import com.xxl.job.core.log.XxlJobLogger; import org.springframework.stereotype.Component; @JobHandler(value="myJobHandler") @Component public class MyJobHandler extends IJobHandler { @Override public ReturnT<String> execute(String param) throws Exception { XxlJobLogger.log("Hello, world!"); return SUCCESS; } }
-
在本例中,创建了一个名为
MyJobHandler
的作业类,该类继承了XXL-JOB的IJobHandler
类。可以在execute方法中编写定时执行的代码。
还需要通过注解@JobHandler
声明作业处理器名称,并在作业配置中将作业处理器与作业关联。 -
优点:
- 操作简单,集成容易。
- 多种任务执行器类型,支持更多的任务类型。
- 支持可视化的调度中心,调度管理更加方便。
-
缺点:
- 比较适合定时任务数量较多,任务类型较为丰富的情况,对于简单的定时任务使用稍显繁琐。
三、共同点和不同点
技术方案 | 共同点 | 不同点 |
---|---|---|
Thread.sleep() | 简单易用 | 不支持复杂的定时任务类型,不支持分布式 |
Timer类 | 简单易用,轻量级 | 不支持复杂的定时任务类型,不支持分布式 |
ScheduledExecutorService | 简单易用,支持多种定时任务类型,可灵活配置,支持并发调度 | 不支持分布式,任务执行结果管理不够方便 |
Quartz框架 | 支持多种定时任务类型,支持分布式、任务持久化 | 配置较为繁琐,依赖比较大 |
Elastic-Job框架 | 支持多种定时任务类型,支持分布式、任务持久化 | 配置较为复杂 |
PowerJob框架 | 支持多种定时任务类型,支持分布式、任务持久化po | 配置较为繁琐 |
Spring Task | 集成简单,支持注解配置 | 不支持分布式,不支持任务持久化 |
Xxl-job | 操作简单,支持多种任务执行器类型,支持可视化的调度中心成就管理 | 比较适合定时任务数量较多,任务类型较为丰富的情况 |
总结
总的来说,各个技术方案都有它们的优缺点,根据实际业务需求、技术需求和团队技术状况等,选择合适的技术方案是非常重要的。
相关文章:

【技术选型】Java 定时任务
文章目录 背景一、基础1.1 Cron表达式1.2 定时任务的三大组成部分 二、Java做定时任务的技术方案比较2.1、JDK seelp实现定时任务2.2、JDK Timer & TimerTask 实现定时任务2.3、JDK ScheduledExecutorService2.4、Quartz框架2.5、Spring Task 中的 schedule2.6、Elastic-Jo…...

让你立刻学会指针
☃️个人主页:fighting小泽 🌸作者简介:目前正在学习C语言和数据结构 🌼博客专栏:C语言学习 🏵️欢迎关注:评论👊🏻点赞👍🏻留言💪&am…...

重塑元宇宙体验!元宇宙实时云渲染解决方案来了
元宇宙作为人工智能、云计算和数字孪生等前沿技术的结合体,近年来越发受到各大企业重视。 元宇宙的应用场景层出不穷,不仅包括营销推广场景,还有品牌活动和电商销售,能有效提升品宣和商业转化效果。 元宇宙也具有极大的建设价值…...

Node【Global全局对象】
文章目录 🌟前言🌟Global全局对象🌟Global对象属性与方法🌟Global对象属性🌟process🌟Buffer类🌟console 🌟写在最后 🌟前言 哈喽小伙伴们,新的专栏 Node 已…...

【技术】《Netty》从零开始学netty源码(四十一)之PoolChunk
PoolChunk 我们再回顾以下netty中与内存相关的类: 前面我们已经分析了PoolSubpag,本章我们分析PoolChunk,先看下它的属性值: 为了更好的理解这些属性值,我们结合它的构造函数来理解,具体的源码如下: 其…...

新建虚拟机更改ip(连接xshell)
# 查看网络设备 [rootcentos79 ~]# nmcli device DEVICE TYPE STATE CONNECTION ens32 ethernet 已连接 ens32 ens33 ethernet 已连接 ens33 virbr0 bridge 已连接 virbr0 lo loopback 未托管 -- # 查看…...

什么是VBST和PVST?两者有啥区别?
在计算机网络中,VLAN(Virtual Local Area Network,虚拟局域网)是一种将局域网划分为多个逻辑上独立的子网的技术,它可以帮助网络管理员更好地管理网络资源。 在VLAN技术中,STP(Spanning Tree P…...

记录-JavaScript常规加密技术
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 当今Web开发中,数据安全是一个至关重要的问题,为了确保数据的安全性,我们需要使用加密技术。JavaScript作为一种客户端编程语言,可以很好地为数据进行加…...

二十三、高级网络技术及应用——BFD解析
文章目录 前言一、BFD 简介1、概述:2、作用: 二、静态路由调用 BFD1、配置静态 BFD2、配置动态 BFD 三、OSPF联动BFD四、BFD 单臂回声(one arm echo) 前言 BFD:Bidirectional Forwarding Detection,双向转…...

大家经常说的java八股文到底是什么?让我来总结一下吧!
八股文问题集合 面试必看java八股文 问题正在收录中,累了休息一会,如果有需要请,先关注,这几天会更帖子,答案后续补上 文章目录 八股文问题集合问题正在收录中,累了休息一会,如果有需要请&#…...

C++备忘录模式实践:轻松实现撤销与恢复功能
目录标题 引言(Introduction)备忘录模式定义及核心概念(Memento Pattern Definition and Core Concepts)备忘录模式的定义(Definition of Memento pattern)备忘录模式的主要角色(Key roles in M…...

如何选择CDN加速平台?
现如今全球CDN市场规模逐年攀升,在2017年全球CDN市场规模约为75亿美元,到2021年增长到200亿美元左右。我国CDN行业同样保持高速发展,自2017年的135亿元增长到2022年的300亿元左右。但是国内的CDN市场规模仅为全球市场的15%-20%,海外CDN市场空间巨大。 接…...

其实苹果知道自己离不开中国制造,因此悄悄给自己留了后路
苹果在加速离开中国,不过从苹果的做法却又可以看到它其实很清醒地认识到无法离开中国制造,因此它在力推印度制造的时候,其实并没拼尽全力,深刻认识到印度制造和印度市场与中国的差距。 一、印度制造和印度市场与中国的差距 2022年…...

必用WhatsApp营销的4个理由
WhatsApp是世界上最受欢迎的消息传递应用程序。每天有1万新用户加入WhatsApp。各种规模的公司都利用该平台与世界各地的客户进行有效的沟通,这要归功于其广泛的覆盖范围、用户友好的设计和安全的端到端加密。因此,WhatsApp聊天机器人迅速普及。 1.为您的…...

Python从入门到精通9天(异常的处理)
异常处理 异常处理语句多个异常raise关键字常见的异常类型自定义异常 异常处理语句 在了解异常处理之前,我们先对它的语句进行说明,如下: try:表示测试代码块以查找错误 except:表示处理错误 finally:表…...

微服务学习——Docker
初识Docker 项目部署的问题 大型项目组件较多,运行环境也较为复杂,部署时会碰到一些问题: 依赖关系复杂,容易出现兼容性问题开发、测试、生产环境有差异 Docker Docker如何解决依赖的兼容问题的? 将应用的Libs(函数库)、 Deps…...

QMS-云质说质量 - 5 解决中小企业质量问题的钥匙在哪里?
云质QMS原创 转载请注明来源 作者:王洪石 引言 一个小小的质量问题可能引发蝴蝶效应 日常生活中,我们每天都会遇到各种各样的问题,并随着它们喜怒哀乐。企业也不例外,即使有很好的管理体系以及非常高素质的员工,一些错…...

基于Java+Spring+vue+element社区疫情服务平台设计和实现
基于JavaSpringvueelement社区疫情服务平台设计和实现 博主介绍:5年java开发经验,专注Java开发、定制、远程、指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java项目精品实战案例《500套》 欢迎点赞 收藏 ⭐留言 文末获取源码联系方式 …...

实战项目:手把手带你实现一个高并发内存池
项目介绍 1.这个项目做的是什么? 当前项目是实现一个高并发的内存池,他的原型是google的一个开源项目tcmalloc,tcmalloc全称Thread-Caching Malloc,即线程缓存的malloc,实现了高效的多线程内存管理,用于替…...

原理这就是索引下推呀
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 索引下推是之前面试的时候遇到的一个面试题,当时没有答上来,今天来学习一下。 介绍索引下推之前先看一下MySQL基…...

个人通讯录(二)
个人通讯录(二) 需求: 通讯录(phone)用来保存若干个联系人的信息,且可以按照联系人姓名的拼音升序排序。要求通讯录提供一下功能: 1.添加联系人信息 2.删除指定联系人信息 3.修改指定联系人…...

DockerK8S常见面试知识
Docker docker的工作原理 docker是一个client-server结构的系统,docker守护进程运行在宿主机上,守护进程从客户端接受命令并管理运行在主机上的容器,容器是一个运行时环境,这就是我们说的集装箱 docker组成部分 1、docker cli…...

tcpdump arping nsenter
tcpdump 参数说明 tcpdump 是一款常用的网络抓包工具,它可以捕获网络数据包并进行分析。tcpdump 的参数非常多,下面是一些常用的参数说明: -i:指定要监听的网络接口,如 -i eth0。 any-n:禁用地址解析&…...

Python - 简单快速回忆基础语法
Python 是一种高级编程语言,易学易用 以下是 Python 基础语法的概述: 注释 Python 使用 # 符号来注释代码行。代码行 # 后的所有内容都将被认为是注释,不会被解释器执行,只是对代码的注释说明 # 这是一条注释 print("Hel…...

蓝牙耳机接打电话哪个比较好?接打电话最好的蓝牙耳机
技术已经发展到如此程度,耳机可以淹没嘈杂环境中不断出现的杂音,同时还能让我们在通话、音乐和娱乐方面保持清晰,既然如此,我们就来整理一下2023年适合通话和娱乐的无线耳机清单。 一、南卡小音舱Lite2蓝牙耳机 参考价格&#x…...

DeepSORT中的卡尔曼滤波
本文是看了DeepSORT方法视频之后,关于其中使用的卡尔曼滤波的理解 DeepSORT视频链接 首先贴几个比较好的,与本文由有关的几个帖子 图说卡尔曼滤波,一份通俗易懂的教程 卡尔曼滤波(Kalman Filter)原理与公式推导 卡尔…...

【Linux网络服务】SSH远程访问及控制
一、openssh服务器 1.1ssh协议 SSH(Secure Shell)是一种安全通道协议,主要用来实现字符界面的远程登录、远程 复制等功能; SSH 协议对通信双方的数据传输进行了加密处理,其中包括用户登录时输入的用户口令࿱…...

AutoGPT的出现,会让程序员失业吗?
最近,一个叫AutoGPT的模型火了,在GitHub上线数周Star数就直线飙升。截至目前,AutoGPT的Star数已经达到87k,马上接近90k,超过了PyTorch的65k。 根据AutoGPT的命名,就可以发现其神奇之处在于“auto”&#x…...

微信小程序php+vue 校园租房指南房屋租赁系统
本着诚信的原则,平台必须要掌握出租方必要的真实可信的信息,这样就可以防止欺诈事件的发生,事后也可以联系找到出租方。并且租金等各方面规范标准化,在这易租房诚信可信的平台让承租方与出租方充分有效对接,既方便了承…...

水果FL Studio21最新中文完整版下载更新及内容介绍
简单总结一下,本次小版本更新最重要的内容,我个人认为是对于M1芯片的适配。其余的比如EQ2,3x这些我们很熟悉的插件虽说也有更新,但是估计并没有特别大的改动。我个人的话会先放一段时间,等下次有其他更让我感兴趣的内容…...