网站首页 > java教程 正文
定时任务简单来说就是在指定时间,以指定的频率来执行一个方法,而在 Java 中我们又该如何实现呢?
今天介绍的都是最原始的方式,开启一个线程,让它睡一会跑一次这也就达到了定频率的执行 run 方法,我们只需要将业务逻辑写在 run 方法中即可。
import java.util.Date;
public class ThreadTest {
public static void main(String[] args) {
// 设置执行周期
final long timeInterval = 3000;
Runnable runnable = new Runnable() {
public void run() {
while (true) {
System.out.println("Task Run ... " + new Date());
try {
Thread.sleep(timeInterval);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
我想使用线程来执行定时任务应该是所有牛逼定时器的核心所在了吧,下面介绍一种用起来更加顺手的方式 Timer 定时器。
Timer 定时器可以简单的理解为有且仅有一个后台线程对多个业务方法进行定时定频率调度的工具。
实现 Timer 定时任务需要一个 Timer 工具类和 TimerTask 实现类,实现类中用于编写任务的逻辑代码。
Timer 定时器中包含一个 TimerTask 的队列和一个 TimerThread 后台线程。注意喽,Timer 中任务的执行都依赖于这一个后台线程呢。
下面看一段示例代码
public class MyTask extends TimerTask{
private String name;
public MyTask(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public void run() {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sf.format(new Date());
System.out.println("exec MyTask ... 当前时间为:" + format);
System.out.println(this.name +" 正在执行!" + sf.format(new Date()));
}
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask task1 = new MyTask("Tasks 1");
TimerTask task2 = new MyTask("Tasks 2");
Calendar calendar1 = Calendar.getInstance();
calendar1.add(Calendar.SECOND, 3);
Calendar calendar2 = Calendar.getInstance();
calendar2.add(Calendar.SECOND, 5);
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String format = sf.format(new Date());
System.out.println("当前时间为:" + format);
timer.schedule(task1, calendar1.getTime(), 3000L);
timer.schedule(task2, calendar2.getTime(), 3000L);
}
}
API 之间的大致关系 Timer - TimerThread - TaskQueue - MyTask - run 当然最终执行的方法肯定是我们自定义任务中的 run 方法。因为我们自定义的任务已经继承了 TimerTask ,而这个类已经实现了 Runnable 接口。
简单说一下定时器中启动任务方法的不同。即 schedule 和 scheduleAtFixedRate 方法的区别?
分为两种情况:
1 首次执行时间早于当前的时间
schedule:以当前时间为准,然后依次按照时间间隔执行任务。
scheduleAtFixedRate: 以首次执行的时间为准,过去的时间没有执行任务的次数会在首次执行的时候补上。
2 任务执行所需时间超过任务执行周期时间
schedule:下一次执行的时间以上一次执行完成的时间为准,会存在一直延后执行的情况。
scheduleAtFixedRate: 下一次执行的时间以上一次执行开始的时间为准,不会延后,但是会存在并发的情况。
还有两个锦上添花的方法。cancel 和 purge,其中 cancel 又分为 TimerTask 单个任务的取消和 Timer 整个定时器的取消。而 Timer 调用 purge 可以返回已经取消的任务数量。
Timer 的缺陷
1 并发操作时的缺陷,这是因为 Timer 的后台只有一个执行线程导致的。
2 当任务抛出异常时的缺陷。如果 TimerTask 抛出 RuntimeException,Timer 会停止所有任务的执行。
如何解决?Java 中提供了一个工具类 ScheduledExecutorService 这个类就可以解决上述的问题。
其实原理很简单,Timer 中只有一个执行线程,绑定了多个任务,所以容易出问题,那解决的方案就是创建一个线程池,多个线程来完成多个任务即可。
但是一般我们想使用定时器来完成某个工作,任务简单点的,使用 Timer 就行,我就看到过有的项目中使用这个。
若是真的非常复杂的定时任务,比方说对时间有要求、任务的数量和执行次数有限制的,可以使用较为复杂的一个定时器框架 Quartz 。关于 Quartz,请听下回分解……
多说一句,Quartz 拥有后台执行线程池能够使用多个线程执行任务,所以,你看,核心还是多线程。
猜你喜欢
- 2024-09-21 分布式定时任务调度框架实践(分布式定时任务解决方案)
- 2024-09-21 再见 Spring Task,这个定时任务框架真香
- 2024-09-21 学会这10种定时任务,有点飘了...
- 2024-09-21 硬核!最全的延迟任务实现方式汇总!附代码(强烈推荐)
- 2024-09-21 linux定时任务(linux定时任务清理日志)
- 2024-09-21 SpringBoot第十八篇:定时任务(Scheduling Tasks)
- 2024-09-21 Java | 一分钟掌握定时任务 | 3 - 单机定时之Timer
- 2024-09-21 探究 Spring 的定时任务配置(spring定时任务时间配置规则)
- 2024-09-21 如何实现定时任务- Java Timer/TimerTask 源码原理解析
- 2024-09-21 JAVA架构师之路-教你如何去实现一个分布式定时任务
你 发表评论:
欢迎- 最近发表
-
- class版本不兼容错误原因分析(class更新)
- 甲骨文Oracle公司为Java的最新LTS版本做出改进
- 「版本发布」Minecraft Java开发版 1.19.4-pre1 发布
- java svn版本管理工具(svn软件版本管理)
- 我的世界1.8.10钻石在第几层(我的世界1.7.2钻石在哪层)
- Java开发高手必备:在电脑上轻松切换多个JDK版本
- 2022 年 Java 开发报告:Java 8 八年不到,开发者都在用什么?
- 开发java项目,选择哪个版本的JDK比较合适?
- Java版本选型终极指南:8 vs 17 vs 21特性对决!大龄程序员踩坑总结
- POI Excel导入(poi excel导入附件)
- 标签列表
-
- 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)
本文暂时没有评论,来添加一个吧(●'◡'●)