一、使用
相同点
- 任务执行未超时,则下次执行时间 = 上次执行开始时间 + period
- 任务执行超时,则下次执行时间 = 上次执行结束时间
不同点
- schedule在错过以后会按照自己的节奏继续走,可能会导致丢失任务,但时间间隔稳定。
- scheduleAtFixedRate在错过后,会努力追赶进度,以确保保持执行频率的稳定。
代码示例
我们进行一个简单的测试,在下面的代码中,每3秒就会有一个间隔5秒的线程休眠(模拟超时),对比一下二者输出数据的区别。
package com; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TimerTest { public static void main(String[] args) { // 任务此时已经启动 Timer t = new Timer(); TimerTask task = new CustomTimerTask("test"); // 添加任务 /* * schedule 保持间隔时间的稳定 * scheduleAtFixedRate 保持执行频率的稳定 */ t.schedule(task, new Date(), 2000); // t.scheduleAtFixedRate(task, new Date(), 2000); } } class CustomTimerTask extends TimerTask { private String name; int count = 1; private final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public CustomTimerTask(String name) { this.name = name; } @Override public void run() { try { System.out.println("线程 : " + count); System.out.println("startTime = " + dateFormatter.format(new Date())); if (count % 3 == 0) { Thread.sleep(5000); } count++; System.out.println("endTime = " + dateFormatter.format(new Date()) + "\r\n"); } catch (InterruptedException e) { e.printStackTrace(); } } }
输出数据对比
schedule
线程 : 1
startTime = 2023-02-25 10:20:28
endTime = 2023-02-25 10:20:28线程 : 2
startTime = 2023-02-25 10:20:30
endTime = 2023-02-25 10:20:30线程 : 3
startTime = 2023-02-25 10:20:32
endTime = 2023-02-25 10:20:37线程 : 4
startTime = 2023-02-25 10:20:37
endTime = 2023-02-25 10:20:37线程 : 5
startTime = 2023-02-25 10:20:39
endTime = 2023-02-25 10:20:39线程 : 6
startTime = 2023-02-25 10:20:41
endTime = 2023-02-25 10:20:46线程 : 7
startTime = 2023-02-25 10:20:46
endTime = 2023-02-25 10:20:46线程 : 8
startTime = 2023-02-25 10:20:48
endTime = 2023-02-25 10:20:48线程 : 9
startTime = 2023-02-25 10:20:50
endTime = 2023-02-25 10:20:55线程 : 10
startTime = 2023-02-25 10:20:55
endTime = 2023-02-25 10:20:55线程 : 11
startTime = 2023-02-25 10:20:57
endTime = 2023-02-25 10:20:57
可以看到,schedule在线程4的位置,它的开始时间是上一个线程的结束时间,它有在努力追赶,但后续并没有把之前落下的线程补回来。
scheduleAtFixedRate
线程 : 1
startTime = 2023-02-25 10:18:59
endTime = 2023-02-25 10:18:59线程 : 2
startTime = 2023-02-25 10:19:01
endTime = 2023-02-25 10:19:01线程 : 3
startTime = 2023-02-25 10:19:03
endTime = 2023-02-25 10:19:08线程 : 4
startTime = 2023-02-25 10:19:08
endTime = 2023-02-25 10:19:08线程 : 5
startTime = 2023-02-25 10:19:08
endTime = 2023-02-25 10:19:08线程 : 6
startTime = 2023-02-25 10:19:09
endTime = 2023-02-25 10:19:14线程 : 7
startTime = 2023-02-25 10:19:14
endTime = 2023-02-25 10:19:14线程 : 8
startTime = 2023-02-25 10:19:14
endTime = 2023-02-25 10:19:14线程 : 9
startTime = 2023-02-25 10:19:15
endTime = 2023-02-25 10:19:20线程 : 10
startTime = 2023-02-25 10:19:20
endTime = 2023-02-25 10:19:20线程 : 11
startTime = 2023-02-25 10:19:20
endTime = 2023-02-25 10:19:20
同样是线程4的位置,它的开始时间是上一个线程的结束时间,并且在其后还有一个线程5,说明scheduleAtFixedRate还是在很努力地加油想把之前落下的线程补回来的。