定时器在开发中使用的场景并不少
常见的有
1、timer
2、ScheduledThreadPool是timer的替代品
3、Spring 提供的 @Scheduled Spring Task
4、定时任务框架 : Quartz 分布式定时任务
本篇文章主要讲的是:Timer
Timer简介
Timer类是Java提供线程用于定时任务调用的工具类,他的线程是安全的。
//构造函数
//创建一个定时器
public Timer() {
this("Timer-" + serialNumber());
}
//创建一个新的定时器,可以指定其作为守护程序运行
public Timer(boolean isDaemon) {
this("Timer-" + serialNumber(), isDaemon);
}
//创建一个新的定时器,并对其命名
public Timer(String name) {
thread.setName(name);
thread.start();
}
//创建一个新的定时器,对其命名或指定器是否做为守护线程运行
public Timer(String name, boolean isDaemon) {
thread.setName(name);
thread.setDaemon(isDaemon);
thread.start();
}
方法的使用
package com.lee.schedule.jdk;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
/**
* @author XMLee
* @date 2022/4/18 16:31
*/
public class TimerTaskTest {
public static void main(String[] args) {
Timer timer = new Timer();
// 1秒之后 执行任务,只执行一次
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis() / 1000 + "执行了任务");
}
}, 1000L);
System.out.println(System.currentTimeMillis() / 1000);
================================================================================================================
//执行时间 <= 当前时间 任务会立马执行
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis() / 1000 + "执行了任务");
}
}, new Date(System.currentTimeMillis() - 1000L));
System.out.println(System.currentTimeMillis() / 1000);
================================================================================================================
// 延迟1秒之后执行任务,然后每隔2秒执行任务
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis() / 1000 + "执行了任务");
}
}, 1000L, 2000L);
System.out.println(System.currentTimeMillis() / 1000);
================================================================================================================
// 执行时间 <=当前时间 则任务立马执行 然后每隔2秒执行任务
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis() / 1000 + "执行了任务");
}
}, new Date(System.currentTimeMillis() - 1000L), 2000L);
System.out.println(System.currentTimeMillis() / 1000);
================================================================================================================
//延迟3秒,最后每隔1秒执行一次
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis() / 1000 + "执行了任务");
}
}, 3000L, 1000L);
System.out.println(System.currentTimeMillis() / 1000);
================================================================================================================
//执行时间 <=当前时间 任务立马执行 并会计算过期该执行的次数并且执行,最后每隔1秒执行一次
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
}
}, new Date(System.currentTimeMillis() - 3000L), 1000L);
System.out.println(System.currentTimeMillis() / 1000);
}
}
schedule()和scheduleAtFixedRate()区别
相同点
1、方法schedule 和方法 scheduleAtFixedRate 都会按顺序执行,所以不用考虑非线程安全的情况。
2、方法schedule 和方法 scheduleAtFixedRate 如果执行任务的时间没有被延迟,那么下一次任务的执行时间参考的是上一次的任务的"开始"时的时间来计算的。
3、方法schedule 和方法 scheduleAtFixedRate 如果执行任务的时间被延迟了,那么下一次任务的执行时间参考的是上一次任务"结束"时的时间来计算。
不同点
schedule 和 scheduleAtFixedRate在使用上基本没什么差别,scheduleAtFixedRate 具有追赶执行性,如果任务的执行时间<=当前时间,scheduleAtFixedRate()会立马执行任务**,并且会计算过期时间里面,这个任务需要执行的次数,**并执行,最后按照设置的周期进行执行。
注意事项以及替代品:ScheduledThreadPool
替代品的意思就是,Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用ScheduledExecutorService则没有这个问题。
package com.lee.schedule.jdk;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author XMLee
* @date 2022/4/18 17:05
*/
public class TimerTaskTest2 {
public static void main(String[] args) {
Timer timer = new Timer();
//Timer运行多个TimeTask时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行
for (int i = 0; i < 100; i++) {
int finalI = i;
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(finalI);
if (finalI == 10) {
throw new RuntimeException();
}
}
},1000L);
}
//Timer
// 优化方案 使用ScheduledExecutorService则没有这个问题。
// scheduledExecutorService.scheduleAtFixedRate() 按照固定频率
// scheduledExecutorService.scheduleWithFixedDelay() 如果任务时间超过固定频率,按照任务实际时间延后
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
for (int i = 0; i < 100; i++) {
int finalI = i;
scheduledThreadPool.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(finalI);
if (finalI == 20) {
throw new RuntimeException();
}
}
}, 1, TimeUnit.SECONDS);
}
}
}
其他定时器的文章
Spring 提供的 @Scheduled Spring Task:暂无
定时任务框架 : Quartz 分布式定时任务:暂无