涉县网站设计,电子贺卡制作,注册外国网站,写文章免费的软件目录 前言
正文
1.方法 schedule(TimerTask task, Date time) 的测试
#xff08;1#xff09;执行任务的时间晚于当前时间(在未来执行)的效果
#xff08;2#xff09;线程TimerThread不销毁的原因
#xff08;3#xff09;使用 public void cancel() 方法实现 T…目录 前言
正文
1.方法 schedule(TimerTask task, Date time) 的测试
1执行任务的时间晚于当前时间(在未来执行)的效果
2线程TimerThread不销毁的原因
3使用 public void cancel() 方法实现 TimerThread 线程销毁
4执行任务的时间早于当前时间(立刻运行的效果
5在定时器中执行多个 TimerTask 任务
6延时执行 TimerTask 的测试
2.方法 schedule(TimerTask task, long delay, long period)
1执行任务的时间晚于当前时间(在未来执行)的效果
2执行任务的时间早于当前时间立即执行的效果
3延迟执行 TimerTask 的测试
4TimerTask 类中的 cancel() 方法
5类 Timer 中的 cancel() 方法
6间隔执行任务的算法
7Timer 类中的 cancel() 方法的注意事项
3.方法 schedule(TimerTask task,long delay) 的测试
4.方法 schedule(TimerTask task,long delay,long period) 的测试。
5.方法 public void scheduleAtFixedRate(TimerTask task, Date firstTime,long period)的测试
1测试 schedule 方法任务不延时(Date 类型)
2测试 schedule 方法任务不延时(Long 类型)
3测试 schedule 方法任务延时(Date 类型)
4测试 schedule 方法任务被延时(Long 类型)
5测试 scheduleAtFixedRate 方法任务不延时(Date 类型)
6测试 scheduleAtFixedRate 方法任务不延时(Long 类型)
7测试 scheduleAtFixedRate 方法任务延时(Date 类型)
8测试 scheduleAtFixedRate 方法任务延时(Long 类型)
9验证 schedule 方法不具有追赶特性
10验证 scheduleAtFixedRate 方法具有追赶性 前言 定时/计划功能在移动开发领域使用较多比如Android技术定时功能在Java种主要通过Timer类实现因为它在内部还是使用多线程的方式进行处理所以和线程技术还是有非常大的关联。 正文 在 JDK 库中 Timer 类主要负责计划任务的功能 也就是在指定的时间开始执行某一个任务Timer类的方法列表如图 Timer类的主要作用就是设置计划任务封装任务的类却是 TimerTask该类的结构图 实现了Runnable接口。
因为TaskTimer是一个抽象类所以执行任务的代码要放入Timer-Task的子类中。
1.方法 schedule(TimerTask task, Date time) 的测试
该方法的作用是在指定日期的执行一次某一任务。
1执行任务的时间晚于当前时间(在未来执行)的效果
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class schedule {static class MyTask extends TimerTask{Overridepublic void run() {System.out.println(任务执行了时间为System.currentTimeMillis());}}public static void main(String[] args) throws InterruptedException {long nowTime System.currentTimeMillis();System.out.println(当前时间为nowTime);long scheduleTime (nowTime10000L);System.out.println(计划时间为scheduleTime);MyTask task new MyTask();Timer timer new Timer();Thread.sleep(1000);timer.schedule(task,new Date(scheduleTime));Thread.sleep(Integer.MAX_VALUE);}}
运行后的效果如图
10s 之后任务成功执行。任务虽然执行完了但线程还未销毁呈红色状态说明内部还有非守护线程正在执行从 jvisualvm.exe工具中也得到了证实程序运行 10s之后名为 Timer-0 的线程还在运行效果如图
下面将介绍这种情况。
2线程TimerThread不销毁的原因
进程不销毁的原因是在创建 Timer 类时启动了一个新的非守护进程JDK 源代码如下 /*** Creates a new timer. The associated thread does inot/i* {linkplain Thread#setDaemon run as a daemon}.*/public Timer() {this(Timer- serialNumber());} 此构造方法调用的是如下构造方法。 private final TimerThread thread new TimerThread(queue);public Timer(String name) {thread.setName(name);thread.start();}
查看构造方法可知创建 一个Timer类时在内部就启动了 1 个新的线程用新启动的这个线程去执行计划任务TimerThread是线程类源代码如下 /*** This helper class implements the timers task execution thread, which* waits for tasks on the timer queue, executions them when they fire,* reschedules repeating tasks, and removes cancelled tasks and spent* non-repeating tasks from the queue.*/
class TimerThread extends Thread {
那么这个新启动的线程并不是守护线程了而且一直在运行。一直在运行的原因是新线程内部有一个死循环TimeThread.java 类中的 mainLoop() 方法代码如下。
private void mainLoop() {while (true) {try {TimerTask task;boolean taskFired;synchronized(queue) {// Wait for queue to become non-emptywhile (queue.isEmpty() newTasksMayBeScheduled)queue.wait();if (queue.isEmpty())break; // Queue is empty and will forever remain; die// Queue nonempty; look at first evt and do the right thinglong currentTime, executionTime;task queue.getMin();synchronized(task.lock) {if (task.state TimerTask.CANCELLED) {queue.removeMin();continue; // No action required, poll queue again}currentTime System.currentTimeMillis();executionTime task.nextExecutionTime;if (taskFired (executionTimecurrentTime)) {if (task.period 0) { // Non-repeating, removequeue.removeMin();task.state TimerTask.EXECUTED;} else { // Repeating task, reschedulequeue.rescheduleMin(task.period0 ? currentTime - task.period: executionTime task.period);}}}if (!taskFired) // Task hasnt yet fired; waitqueue.wait(executionTime - currentTime);}if (taskFired) // Task fired; run it, holding no lockstask.run();} catch(InterruptedException e) {}}}
private void mainLoop()方法内部使用 while(true) 死循环一直执行计划任务并不退出 while(true)死循环依据源代码的执行流程除非是满足 if (queue.isEmpty()) 条件才执行 break 退出 while(true)死循环退出逻辑的核心源代码如下 while (queue.isEmpty() newTasksMayBeScheduled)queue.wait();if (queue.isEmpty())break;
上面的源代码逻辑如下
1使用 while 循环对 queue.isEmpty() newTasksMayBeScheduled 条件进行判断。
2当 两端都为 true 时执行 wait() 方法使当前线程被暂停运行等待被唤醒。
3唤醒的时机是执行了 public void schedule(TimeTask task,Date time)方法说明要执行新的任务了。
4唤醒后 while 继续判断 queue.isEmpty() newTaskMayBeScheduled 条件如果有新的任务被安排则 queue.isEmpty() 结果为 false最终结果为是 false会继续执行下面的 if 语句。
5if(queue.isEmpty()) 中的 queue.isEmpty() 结果为 true说明队列为空那么执行 break 语句退出 while(true) 死循环。
6执行 public void cancel() 方法会使布尔变量 newTaskMayBeScheduled 的值由 true 变成 false。
7如果不执行 public void cancel()变量 newTaskMayBeScheduled 的值就不会是 false一直呈死循环的状态进程不销毁就是这个原因public void cancel() 方法源代码如下。
public void cancel() {synchronized(queue) {thread.newTasksMayBeScheduled false;queue.clear();queue.notify(); // In case queue was already empty.}}
上面 7 步就是进程不消毁的原因以及退出死循环 while(true) 的逻辑。
3使用 public void cancel() 方法实现 TimerThread 线程销毁
Timer 类中 public void cancel() 方法的作用是终止此计时器丢弃当前所有已安排的任务。这不会干扰当前正在执行的任务(如果存在)。一旦终止了计时器那么它的执行线程也会终止并且无法根据它安排更多的任务。注意在此计算器调用的计时器任务的 run() 方法内调用此方法就可以确保正在执行的任务是此计算器的最后一个任务。虽然可以重复调用此方法但是第二次和后续调用无效。
根据上面的源代码分析可知当队列中为空并且 newTaskMayBeScheduled 值是 false 时退出 while(true) 死循环导致 TimerThread 线程结束运行并销毁。
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class Test {static class MyTask extends TimerTask {Overridepublic void run() {System.out.println(任务执行了时间为System.currentTimeMillis());}}public static void main(String[] args) throws InterruptedException {long nowTime System.currentTimeMillis();System.out.println( 当前时间为 nowTime);long scheduleTime (nowTime 15000L);System.out.println( 计划时间为scheduleTime);MyTask task new MyTask();Timer timer new Timer();timer.schedule(task,new Date(scheduleTime));Thread.sleep(18000);timer.cancel();Thread.sleep(Integer.MAX_VALUE);}
}
程序运行18秒之后从 jvisualvm.exe工具中可以看到名称为 Timer-0 的线程 TimerThread被销毁在已完成的线程中了效果如图 虽然 TimerThread 线程销毁了但进程还是呈红色状态这时因为main 线程一直在执行 Thread.sleep(Integer.MAX_VALUE) 代码控制台输出如下 4执行任务的时间早于当前时间(立刻运行的效果
如果执行任务的时间早于当前时间则立即执行任务。
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class Test {static class MyTask extends TimerTask {Overridepublic void run() {System.out.println(任务执行了时间为System.currentTimeMillis());}}public static void main(String[] args) throws InterruptedException {long nowTime System.currentTimeMillis();System.out.println( 当前时间为 nowTime);long scheduleTime (nowTime - 5000);System.out.println( 计划时间为scheduleTime);MyTask task new MyTask();Timer timer new Timer();timer.schedule(task,new Date(scheduleTime));}
}
效果如图 5在定时器中执行多个 TimerTask 任务
可以在定时器中执行多个 TimerTask 任务。
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class Test {static class MyTask extends TimerTask {Overridepublic void run() {System.out.println(任务执行了时间为System.currentTimeMillis());}}public static void main(String[] args) throws InterruptedException {long nowTime System.currentTimeMillis();System.out.println( 当前时间为 nowTime);long scheduleTime1 (nowTime 5000);long scheduleTime2 (nowTime 8000);System.out.println( 计划时间1为scheduleTime1);System.out.println( 计划时间2为scheduleTime2);MyTask task1 new MyTask();MyTask task2 new MyTask();Timer timer new Timer();timer.schedule(task1,new Date(scheduleTime1));timer.schedule(task2,new Date(scheduleTime2));}
}
程序运行结果如图 6延时执行 TimerTask 的测试
因为TimerTask是以一个队列得到方式一个一个被顺序执行的所以执行的时间有可能和预期的时间不一致。因为前面的任务有可能消耗的时间较长所以后面的任务运行的时间也被延后请看下面的示例
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class taskLater {static class MyTaskA extends TimerTask {Overridepublic void run() {try {System.out.println(A begin timer System.currentTimeMillis());Thread.sleep(20000);System.out.println(A end Timer System.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}static class MyTaskB extends TimerTask{Overridepublic void run() {System.out.println(B begin timerSystem.currentTimeMillis());System.out.println(B end timerSystem.currentTimeMillis());}}public static void main(String[] args) {long nowTime System.currentTimeMillis();System.out.println(当前时间为nowTime);long scheduleTime1 nowTime;long scheduleTime2 nowTime5000;System.out.println(计划时间1为scheduleTime1);System.out.println(计划时间2为scheduleTime2);MyTaskA taskA new MyTaskA();MyTaskB taskB new MyTaskB();Timer timer new Timer();timer.schedule(taskA,new Date(scheduleTime1));timer.schedule(taskB,new Date(scheduleTime2));}
}
程序运行结果如图 在代码中long scheduleTime2 now 5000 原计划是执行任务1 和任务 2 的运行间隔时间为 5 秒由于 task1 执行任务需要 20 秒因此 task1 的结束时间就是 task2 的开始时间task2 不再以 5 秒作为参考 而是以 20 秒作为参考究其原理是创建了 1 个Timer 类导致创建了 1 个TimerThread 线程1 个TimerThread 线程管理 1 个队列在队列中得按顺序运行任务。
2.方法 schedule(TimerTask task, long delay, long period)
该方法的作用是在指定的日期之后按指定的间隔周期无限循环地执行某一任务。
1执行任务的时间晚于当前时间(在未来执行)的效果 import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class timerTest2_period {static class MyTask extends TimerTask{Overridepublic void run() {System.out.println(任务执行了时间为System.currentTimeMillis());}}public static void main(String[] args) {long nowTime System.currentTimeMillis();System.out.println(当前时间为nowTime);long scheduleTime (nowTime10000);System.out.println(计划时间为scheduleTime);MyTask task new MyTask();Timer timer new Timer();timer.schedule(task,new Date(scheduleTime),4000L);}}
程序运行结果如图 从运行结果来看每隔 4 秒运行一次 TimerTask 任务并且是无限期重复执行任务。
2执行任务的时间早于当前时间立即执行的效果
如果计划时间早于当前时间则立即执行任务。
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class Test2 {static class MyTask extends TimerTask {Overridepublic void run() {System.out.println(任务执行了时间为System.currentTimeMillis());}}public static void main(String[] args) throws InterruptedException {long nowTime System.currentTimeMillis();System.out.println( 当前时间为 nowTime);long scheduleTime (nowTime - 5000);System.out.println( 计划时间为scheduleTime);MyTask task new MyTask();Timer timer new Timer();timer.schedule(task,new Date(scheduleTime),4000L);}
}
程序运行结果如图 控制台打印的结果是程序运行后立即执行任务并且每隔 4 秒打印一次。
3延迟执行 TimerTask 的测试
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class timerTest2_periodLater {static class MyTaskA extends TimerTask{Overridepublic void run() {try{System.out.println(A begin timerSystem.currentTimeMillis());Thread.sleep(5000);System.out.println(A end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {long nowTime System.currentTimeMillis();System.out.println(当前时间为 nowTime);System.out.println( 计划时间为 nowTime);MyTaskA taskA new MyTaskA();Timer timer new Timer();timer.schedule(taskA,new Date(nowTime),3000);}
}使用代码 timer.schedule(taskA,new Date(nowTime),3000);是让每个任务执行的间隔时间为 3 秒而运行结果却是 5 秒这是因为在任务中执行了 Thread.sleep(5000) 程序运行结果如图所示 4TimerTask 类中的 cancel() 方法
TimerTask 类中的 cancel() 方法的作用是将自身从任务队列中清楚该方法的源代码如下。 public boolean cancel() {synchronized(lock) {boolean result (state SCHEDULED);state CANCELLED;return result;}}
从方法得到代码可以分析出执行 TimerTask 类中的 cancel() 方法时是将当前 TimerTask 任务得到状态改为 CANCELLED。
测试代码如下
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class TimerTaskCancelMethod {static class MyTaskA extends TimerTask{Overridepublic void run() {System.out.println(A run timerSystem.currentTimeMillis());this.cancel();System.out.println(A 任务自己移除自己);}}static class MyTaskB extends TimerTask{Overridepublic void run() {System.out.println(B run timerSystem.currentTimeMillis());}}public static void main(String[] args) {long nowTime System.currentTimeMillis();System.out.println(当前时间为nowTime);System.out.println(计划时间为nowTime);MyTaskA task1 new MyTaskA();MyTaskB task2 new MyTaskB();Timer timer new Timer();timer.schedule(task1,new Date(nowTime),4000L);timer.schedule(task2,new Date(nowTime),4000L);}
}运行结果如下 TimerTask 类的 cancel() 方法是将自身从任务队列中移除其他任务不受影响。
5类 Timer 中的 cancel() 方法
和 TimerTask 类中的 cancel() 方法清除自身不同Timer 类中 cancel() 方法的作用是将任务队列中全部的任务清空源代码如下。 public void cancel() {synchronized(queue) {thread.newTasksMayBeScheduled false;queue.clear();queue.notify(); // In case queue was already empty.}}
创建新的测试用例
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class TimerCancelMethod {static class MyTaskA extends TimerTask {Overridepublic void run() {System.out.println(A run timerSystem.currentTimeMillis());}}static class MyTaskB extends TimerTask{Overridepublic void run() {System.out.println(B run timerSystem.currentTimeMillis());}}public static void main(String[] args) throws InterruptedException {long nowTime System.currentTimeMillis();System.out.println(当前时间为nowTime);System.out.println(计划时间为nowTime);MyTaskA task1 new MyTaskA();MyTaskB task2 new MyTaskB();Timer timer new Timer();timer.schedule(task1,new Date(nowTime),2000L);timer.schedule(task2,new Date(nowTime),2000L);Thread.sleep(10000);timer.cancel(); //全部任务都取消}
}程序运行 10 秒后进程销毁控制台输出结果如图 全部任务都被清楚并且进程被销毁按钮由红色变成灰色。
6间隔执行任务的算法
当队列中有三个任务 A B C 时这三个任务执行顺序的算法是每次将最后一个任务放入队列头再执行队列头中任务的 run() 方法算法效果如下 1起始顺序为 A B C。 2C A B将 C 放入 AB 之前。 3) B C A将 B 放入 C A之前。 创建新的任务代码如下
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class NewAlgorithm {static class MyTaskA extends TimerTask {Overridepublic void run() {System.out.println(A run timerSystem.currentTimeMillis());}}static class MyTaskB extends TimerTask{Overridepublic void run() {System.out.println(B run timerSystem.currentTimeMillis());}}static class MyTaskC extends TimerTask{Overridepublic void run() {System.out.println(C run timerSystem.currentTimeMillis());}}public static void main(String[] args) {long nowTime System.currentTimeMillis();System.out.println(当前时间为nowTime);System.out.println(计划时间为nowTime);MyTaskA taskA new MyTaskA();MyTaskB taskB new MyTaskB();MyTaskC taskC new MyTaskC();Timer timer new Timer();timer.schedule(taskA,new Date(nowTime),2000L);timer.schedule(taskB,new Date(nowTime),2000L);timer.schedule(taskC,new Date(nowTime),2000L);}
}
运行结果如图 7Timer 类中的 cancel() 方法的注意事项
Timer() 类中的 cancel() 方法有时不一定会停止计划任务而是正常执行。
创建新的项目
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class TimerCancelError {static class MyTaskA extends TimerTask {private int i;public MyTaskA(int i) {super();this.i i;}Overridepublic void run() {System.out.println( 第 i 次没有被cancel取消);}}public static void main(String[] args) throws InterruptedException {int i 0;long nowTime System.currentTimeMillis();System.out.println(当前时间为nowTime);System.out.println(计划时间为nowTime);while(true){i;Timer timer new Timer();MyTaskA taskA new MyTaskA(i);timer.schedule(taskA,new Date(nowTime));timer.cancel();}}
}
程序运行后代码截图
因为 Timer 类中的 cancel() 方法有时并没有争抢到队列锁所以让TimerTask 任务正常执行。
3.方法 schedule(TimerTask task,long delay) 的测试
该方法的作用是以执行 schedule(TimerTask task,long delay) 方法当前的时间为参考时间在此时间基础上延迟指定的毫秒数后执行一次 TImerTask 任务。
import java.util.Timer;
import java.util.TimerTask;public class timerTest3 {static class MyTask extends TimerTask{Overridepublic void run() {System.out.println(运行了时间为System.currentTimeMillis());}}public static void main(String[] args) {MyTask task new MyTask();Timer timer new Timer();System.out.println(当前时间为System.currentTimeMillis());timer.schedule(task,7000L);}
}
程序运行结果如图 任务被延迟 7 秒执行了。
4.方法 schedule(TimerTask task,long delay,long period) 的测试。
该方法的作用是以执行 schedule(TimerTask task,long delay,long period) 方法当前的时间为参考时间在此时间的基础上延迟指定的毫秒数再以某一间隔时间无限次数地执行某一任务。
import java.util.Timer;
import java.util.TimerTask;public class timerTest3 {static class MyTask extends TimerTask{Overridepublic void run() {System.out.println(运行了时间为System.currentTimeMillis());}}public static void main(String[] args) {MyTask task new MyTask();Timer timer new Timer();System.out.println(当前时间为System.currentTimeMillis());timer.schedule(task,3000L,5000);}
}程序运行结果如图 凡是使用方法中带有 period 参数的都是无限循环执行 TimerTask 中的任务。
5.方法 public void scheduleAtFixedRate(TimerTask task, Date firstTime,long period)的测试 schedule 方法和 scheduleAtFixedRate 方法的主要区别在于有没有追赶特性。 1测试 schedule 方法任务不延时(Date 类型)
创建项目测试代码如下
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class timerTest5 {static class MyTask extends TimerTask {Overridepublic void run() {try {System.out.println(begin timerSystem.currentTimeMillis());Thread.sleep(1000);System.out.println( end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {MyTask task new MyTask();long nowTime System.currentTimeMillis();Timer timer new Timer();timer.schedule(task,new Date(nowTime),3000);}
}
运行结果如图 控制台打印结果证明在不延时的情况下如果执行任务的时间没有被延时则下一次执行任务的开始时间是上一次任务的开始时间加上 period 时间。
所谓的 “不延时” 是指执行任务的时间小于 period 间隔时间。
2测试 schedule 方法任务不延时(Long 类型)
import java.util.Timer;
import java.util.TimerTask;public class Test2 {static class MyTask extends TimerTask {Overridepublic void run() {try {System.out.println(begin timerSystem.currentTimeMillis());Thread.sleep(1000);System.out.println( end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {MyTask task new MyTask();System.out.println( 当前时间System.currentTimeMillis());Timer timer new Timer();timer.schedule(task,3000L,4000L);}
}
运行结果如图 控制台打印的结果证明在不延时的情况下如果执行任务的时间没有被延时则第一次执行任务的时间是任务快开始时间加上延时时间接下来执行任务的时间是上一次任务的开始时间加上 period 时间。
3测试 schedule 方法任务延时(Date 类型)
创建测试用例
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class timerTest5 {static class MyTask extends TimerTask {Overridepublic void run() {try {System.out.println(begin timerSystem.currentTimeMillis());Thread.sleep(5000);System.out.println( end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {MyTask task new MyTask();long nowTime System.currentTimeMillis();Timer timer new Timer();timer.schedule(task,new Date(nowTime),2000);}
}
运行结果如图 从控制台打印结果来看在延时的情况下如果执行任务的时间被延时那么下一次任务的执行时间参考的是上一次任务 结束 的时间。
4测试 schedule 方法任务被延时(Long 类型)
测试用例如下
import java.util.Timer;
import java.util.TimerTask;public class Test2 {static class MyTask extends TimerTask {Overridepublic void run() {try {System.out.println(begin timerSystem.currentTimeMillis());Thread.sleep(5000);System.out.println( end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {MyTask task new MyTask();System.out.println( 当前时间System.currentTimeMillis());Timer timer new Timer();timer.schedule(task,3000L,2000L);}
}
运行结果如图 从控制台打印结果来看在延时的情况下如果执行任务的时间被延时那么下一次任务的执行时间参考的是上一次任务 结束 的时间。
5测试 scheduleAtFixedRate 方法任务不延时(Date 类型)
创建新的测试用例本次测试使用 scheduleAtFixedRate 作为测试。
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class timerTest5 {static class MyTask extends TimerTask {Overridepublic void run() {try {System.out.println(begin timerSystem.currentTimeMillis());Thread.sleep(1000);System.out.println( end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {MyTask task new MyTask();long nowTime System.currentTimeMillis();Timer timer new Timer();timer.scheduleAtFixedRate(task,new Date(nowTime),3000);}
}
控制台打印的结果证明在不延时的情况下如果执行任务的时间没有被延时则下一次执行任务的时间是上一次任务的开始时间加上 period 时间。
6测试 scheduleAtFixedRate 方法任务不延时(Long 类型)
创建测试用例
import java.util.Timer;
import java.util.TimerTask;public class Test2 {static class MyTask extends TimerTask {Overridepublic void run() {try {System.out.println(begin timerSystem.currentTimeMillis());Thread.sleep(1000);System.out.println( end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {MyTask task new MyTask();System.out.println( 当前时间System.currentTimeMillis());Timer timer new Timer();timer.scheduleAtFixedRate(task,3000L,4000L);}
}
运行结果如图 控制台打印的结果证明在不延时的情况下如果执行任务的时间没有被延时则下一次执行任务的时间是上一次任务的开始时间加上 period 时间。
7测试 scheduleAtFixedRate 方法任务延时(Date 类型)
创建测试用例 import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class timerTest5 {static class MyTask extends TimerTask {Overridepublic void run() {try {System.out.println(begin timerSystem.currentTimeMillis());Thread.sleep(5000);System.out.println( end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {MyTask task new MyTask();long nowTime System.currentTimeMillis();Timer timer new Timer();timer.scheduleAtFixedRate(task,new Date(nowTime),2000);}
}
运行结果如图 从控制台打印结果来看在延时的情况下如果执行任务的时间被延时那么下一次任务的执行时间参考的是上一次任务 结束 的时间。
8测试 scheduleAtFixedRate 方法任务延时(Long 类型)
创建测试用例
import java.util.Timer;
import java.util.TimerTask;public class Test2 {static class MyTask extends TimerTask {Overridepublic void run() {try {System.out.println(begin timerSystem.currentTimeMillis());Thread.sleep(5000);System.out.println( end timerSystem.currentTimeMillis());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {MyTask task new MyTask();System.out.println( 当前时间System.currentTimeMillis());Timer timer new Timer();timer.scheduleAtFixedRate(task,3000L,2000L);}
}
运行结果如图 从控制台打印结果来看在延时的情况下如果执行任务的时间被延时那么下一次任务的执行时间参考的是上一次任务 结束 的时间。
从上面 8 个运行结果来看schedule 方法和 scheduleAtFixedRate 方法在运行效果上并没有非常明显的区别那它们之间到底有什么区别呢那就是追赶特性。
9验证 schedule 方法不具有追赶特性
创建测试用例
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class Test9 {static class MyTask extends TimerTask{Overridepublic void run() {System.out.println(begin timerSystem.currentTimeMillis());System.out.println( end timerSystem.currentTimeMillis());}}public static void main(String[] args) {MyTask task new MyTask();long nowTime System.currentTimeMillis();System.out.println(现在执行时间nowTime);long runTime nowTime - 20000;System.out.println(计划执行时间runTime);Timer timer new Timer();timer.schedule(task,new Date(runTime),2000);}
}
运行结果如图 从运行结果上来看“1700620549103” 到 ”1700620529103“ 的时间所对应的任务被取消掉不执行了这就是任务不追赶。
10验证 scheduleAtFixedRate 方法具有追赶性
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;public class Test9 {static class MyTask extends TimerTask{Overridepublic void run() {System.out.println(begin timerSystem.currentTimeMillis());System.out.println( end timerSystem.currentTimeMillis());}}public static void main(String[] args) {MyTask task new MyTask();long nowTime System.currentTimeMillis();System.out.println(现在执行时间nowTime);long runTime nowTime - 20000;System.out.println(计划执行时间runTime);Timer timer new Timer();timer.scheduleAtFixedRate(task,new Date(runTime),2000);}
}
运行结果如图 11次开始1次加上{20000/2000}能运行的10次总共11次打印任务时间 “1700621411899” 都是曾经流逝时间的任务追赶也就是将曾经没有执行的任务追加进行执行将 20 秒之内执行任务的次数打印完再每间隔 2 秒执行一次任务。 将两个时间段内的时间所对应的任务被 “弥补” 地执行也就是在指定时间段内的运行次数必须要运行完整这就是任务追赶特性。