网站首页 > java教程 正文
Java中创建和玩转定时任务
定时任务,在日常工作中,可以说是一个算是一个常见的需求场景,比如定时数据校验,数据报表输出,报警等
0. 前言
前面一篇博文《Java并发学习之四种线程创建方式的实现与对比》, 有朋友指出线程池的方式应该算不上新的方式,而应该把Timer方式创建线程加上
这个却是我个人见识不够,写的时候没有想到Timer这种场景了,所以说分享学习记录,不仅仅可以帮助别人,自己也会因此收益
感谢@超大小龙虾 的指正,同时欢迎各位大侠对小弟多多指教
I. 定时任务创建的几种方式
这里给出几种个人接触过的定时任务使用方式(不全,仅供大家参考)
最简单的一种:在线程中执行Thread.sleep(),休眠挂起线程,等待一段时间后再执行
借助Timer和TimerTask实现定时任务
借助调度线程池Executors.newScheduledThreadPool()实现定时任务
借助第三方工具,如spring的定时任务; Quartz(听过没用过);以及其他一些开源工具或公司内的服务
下面简单介绍上面的几种思路,以及一般的使用姿势
1. Thread#sleep方式
严格来讲,这种不太能够算入定时任务的范畴,为什么这么说?
一般我们所说的定时任务可以区分为两种,一种是到了某个点自动执行;另一种就是每隔多长时间执行一次
而这种线程Sleep的方式,则是在运行后,强制使线程进入阻塞状态一段时间,然后再执行后续的逻辑,一般的使用流程是
这里把这个也放在定时任务里,可以看下面结合实例的case中的演示,利用这个sleep也可以非常猥琐的实现定时需求
2. Timer & TimerTask方式
TimerTask 是一个实现 Runnable的抽象类,因此可以将需要定时处理的业务逻辑封装在这个Task里面;然后通过Timer封装类来定时调度
TimerTask的使用姿势和一般的Runnable接口没啥两样
一般使用姿势如下
这个就有意思一点了,可以支持定时执行,也可以支持按一个频率执行,且一般使用可以将上面的步骤进行缩减, 直接这么玩
3.Executors#newScheduledThreadPool线程池方式
Executors提供了一批创建线程池的方式,除了常见的创建固定大小的线程池之外,还有个一就是创建ScheduledExecutorService来实现定时任务调度
借助Executors#newScheduledThreadPool来实现定时任务非常简单
从使用姿势来看,和Timer方式差不离,同样支持定时执行与每隔多长时间执行两种方式
4. spring的定时任务
spring方式就非常强大了,而且支持注解的配置方式,配置完毕,然后在方法上加一个注解,就可以实现定时执行了
常见的使用姿势
而且比较厉害的是,这个还支持cron表达式
II. 结合实例演示四种定时任务使用姿势
来两个实际的应用场景,用上面的四种方式分别实现
case:
系统中有一些统计数据,需要离线计算,每天凌晨计算完之后导入,然后需要一个定时任务,假设凌晨5点数据导入完毕;在5:15分进行校验,判断数据是否正常导入;校验完成之后,45分钟后即六点,将校验结果通知给owner
1. Thread#sleep 实现方式
采用sleep的方式实现定时任务,因为其本身不支持定时的情况,所以就只能比较猥琐的计算需要sleep的时间了
实现代码如下(非精确的实现方式,主要为了演示如何用sleep来实现上面这种场景)
简单说明下上面的实现思路:
采用while(true)死循环,来实现每隔多长时间来执行一次
对于定时触发任务的场景,需要计算指定时间与当前时间的差值,作为sleep的时间
这个实现方式,虽说可以完成目标,但是非常的不优雅,下面来看下Timer的实现方式
2. Timer&TimerTask 实现方式
使用Timer,需要借助TimerTask类,在其中书写定时任务的逻辑,因为case中有一个每隔一天跑一次的定时任务和一个延迟任务,所以这里用到了Timer的两种定时任务使用方式
相比与上一个,稍微好了那么一丢丢,至少从代码结构上来看简洁了很多
3. Executors.newScheduledThreadPool的实现方式
定时任务的方式,用起来和前面差不多,依然是两种方式的混搭
与Timer在用法上不同的一个是这里可以指定延迟的时间单位;但是希望在指定的时间进行执行时,依然还是得计算初始的延迟时间,和sleep使用方式中差不多
上面三中,是jdk本身就支持的定时任务的支持;总得来说,能实现你的需求场景,但是不好用,还得让自己去计算delayTime/sleepTime;讲道理,这对使用者而言,实在是不能更不友好了;
但是在另一方面,若延迟时间比较容易确认的话;或者单纯的使用每隔多长时间调度一次的话,Timer和ScheduledExecutorService两种方式都还不错
Timer 在指定时间执行任务相比较 ScheduledExecutorService 而言优雅一点
ScheduledExecutorService 则胜在使用起来简洁,而且schedule方法可以提交Callable任务,并获取返回值
Thread#sleep方法,则尽量不要这么玩,有点违和
4. 高逼格的Spring定时器
Spring 相比较jdk自带的几种方式而言,我认为,最完美的有两点
支持cron表达式
注解方式,无侵入
配置xml文件
实现业务逻辑
这个实现就简单了,相比较上面而言,添加一个注解,里面配置cron表达式,xml配置下,就可以实现定时任务
III. 小结
1. 本片博文主要介绍了实现定时任务的方式有几种,下面简单小结下四种方式的特点
方式 | 说明 | 特点 |
---|---|---|
Thread#sleep | 线程挂起一段时间 | 通过定时目标与当前时间计算sleepTime,来强制实现定时任务 |
Timer#TimerTask | 异步定时任务 | TimerTask内部实现定时任务逻辑
|
ScheduledExecutorService | 计划任务线程池 |
|
Spring Schedule | spring提供的定时任务 | 支持cron表达式,使用简单,非常简单,超级简单 |
2. 使用Timer方式,也可以算一种新的创建线程方式
3. 使用小建议
不推荐使用 Thread#sleep的方式做定时任务
如指向利用jdk实现定时任务,可以考虑Timer和ScheduledExecutorService
如项目本身就利用到了Spring,可以优先考虑这些优秀的框架提供的服务,用起来特别爽,谁用谁知道
IV. 其他
声明
尽信书则不如,已上内容,纯属一家之言,因本人能力一般,见识有限,如有问题,请不吝指正,感激
相关博文
猜你喜欢
- 2024-09-09 Java 定时器、加密、File类(java定时器时间格式)
- 2024-09-09 100个Java工具类之67:定时执行Timer
- 2024-09-09 JAVA定时器的嵌套实现(java的定时器能不能提供实时保证 可能提前也可能推迟)
- 2024-09-09 Java中分布式定时器实现和原理介绍
- 2024-09-09 Java定时任务——SpringTask(java定时任务的实现方式)
- 2024-09-09 全面了解Java Timer定时器类(java定时器怎么用)
- 2024-09-09 Java多线程19:定时器Timer(java多线程实现方式)
- 2024-09-09 Java中的定时器:java.util.Timer(java中的定时器有哪些)
- 2024-09-09 Java 中如何实现定时任务(java定时任务底层原理)
- 2024-09-09 Java定时任务的五种创建方式,你都会么?
你 发表评论:
欢迎- 最近发表
-
- Java常量定义防暴指南:从"杀马特"到"高富帅"的华丽转身
- Java接口设计原则与实践:优雅编程的艺术
- java 包管理、访问修饰符、static/final关键字
- Java工程师的代码规范与最佳实践:优雅代码的艺术
- 编写一个java程序(编写一个Java程序计算并输出1到n的阶乘)
- Mycat的搭建以及配置与启动(mycat部署)
- Weblogic 安装 -“不是有效的 JDK Java 主目录”解决办法
- SpringBoot打包部署解析:jar包的生成和结构
- 《Servlet》第05节:创建第一个Servlet程序(HelloSevlet)
- 你认为最简单的单例模式,东西还挺多
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)