定时/计算在java中主要使用的是Timer对象,他的内部依然是采用多线程方式进行处理
它有四个构造方法#
方法名 | 作用 |
Timer() | 空参 |
Timer(String name) | 指定名字 |
Timer(boolean isDaemon) | 指定为守护线程 |
Timer(String name,boolean isDaman) | 指定名字,指定为守护线程 |
Timer类的主要作用就是设置计划任务,但是封装任务的类确是TimerTask,TimerTask实现了Runable接口,因此我们要做的也就是重写run方法,定义我们的任务
- 简单使用
public class demo01 extends TimerTask { @Override public void run() { System.out.println("计划执行了, "+new Date()); } public static void main(String[] args) { System.out.println("当前时间 "+ new Date()); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.SECOND,5); Date time = calendar.getTime(); demo01 task = new demo01(); Timer timer = new Timer(); timer.schedule(task,time); System.out.println("主线程结束了..."); } }
程序执行完了,但是进程仍然没有被撤销,呈红色状态,那是因为每创建一个Timer对象,就是启动一条线程,并且这条线程不是守护线程,会一直执行下去
常用的几个Timer对象的API#
1. 安排在指定的时间执行指定的任务,如果时间过去了,立即执行#
void schedule(TimerTask task,Date time)
一个Timer对象,可以拥有多个TimerTask,而TimerTask是以队列的方法,一个一个顺序执行,这也就可能导致执行的时间和预期的时间不一样,因为前面的任务执行的时间可能比较长,那么后面的任务也就被延后了
2. 在指定的日期到达之后,按照指定的时间间隔,执行一次某任务#
schedule(TimerTask task , Date firstTime,Long period)
注意点:
- firstTime晚于当前时间,计划未来
- firstTime早于当前时间,计划立即执行
- 任务依然可能被延迟
3, 以当前时间为准,在此时间基础上延迟指定的时间毫秒数执行一次TimerTask任务#
schedule(TimerTask task, Long delay)
4 .当前的时间为参考,在此时间基础上延迟指定的毫秒数,再以某一个时间间隔,无限次执行某一任务#
schedule(TimerTask task,Long delay,Long period)
5. 测试schedule&scheduleAtFixedRate几种情况#
不延迟 | 描述 |
Date类型 | 下一次执行任务的时间,都是上一次任务开始的时间+period |
Long类型 | 第一次任务执行的时间是任务开始的时间+delay,接下来执行任务的时间是上一次任务开始的时间+priod |
延迟 | 描述 |
Date类型 | 下一次执行任务的时间,都是上一次任务结束的时间+period |
Long类型 | 下一次执行任务的时间是上一次任务结束的时间+priod |
6. 追赶性#
举个例子什么是追赶性,假如说,程序运行到A行代码时,时间是t1,程序继续往下执行,遇到了B行代码,我们希望,B在A前10秒执行给定的任务,可是按照我们的顺序,A已经执行了,那么实现我们的要求就用到了scheduleAtFixedRate的追赶性
示例代码:
/* * schedule的追赶性 * */ public class demo03 extends TimerTask { @Override public void run() { System.out.println("任务开始的时间"+new Date()); System.out.println("任务结束的时间"+new Date()); } public static void main(String[] args) { System.out.println("现在执行的时间+"+new Date()); demo03 task = new demo03(); Calendar instance = Calendar.getInstance(); instance.set(Calendar.SECOND,instance.get((Calendar.SECOND)-10)); Date time = instance.getTime(); System.out.println("计划执行的时间"+ time); Timer timer = new Timer(); timer.scheduleAtFixedRate(task,time,2000); } }
结果:
现在执行的时间+Sat Feb 16 07:17:14 CST 2019 计划执行的时间Sat Feb 16 07:17:07 CST 2019 任务开始的时间Sat Feb 16 07:17:14 CST 2019 任务结束的时间Sat Feb 16 07:17:14 CST 2019 任务开始的时间Sat Feb 16 07:17:14 CST 2019 任务结束的时间Sat Feb 16 07:17:14 CST 2019 任务开始的时间Sat Feb 16 07:17:14 CST 2019 任务结束的时间Sat Feb 16 07:17:14 CST 2019 任务开始的时间Sat Feb 16 07:17:14 CST 2019 任务结束的时间Sat Feb 16 07:17:14 CST 2019 任务开始的时间Sat Feb 16 07:17:15 CST 2019 任务结束的时间Sat Feb 16 07:17:15 CST 2019 任务开始的时间Sat Feb 16 07:17:17 CST 2019 任务结束的时间Sat Feb 16 07:17:17 CST 2019 任务开始的时间Sat Feb 16 07:17:19 CST 2019 任务结束的时间Sat Feb 16 07:17:19 CST 2019 任务开始的时间Sat Feb 16 07:17:21 CST 2019 任务结束的时间Sat Feb 16 07:17:21 CST 2019 任务开始的时间Sat Feb 16 07:17:23 CST 2019 ...
TimerTask与Timer的cancel方法
- TimerTask的cancel()自然由TimerTask对象调用,它本身是任务队列中的一个任务,作用是把自身从任务队列中进行清除
- Timer的cancel()方法**把整个任务队列清除
Timer的cancel的注意事项#
public class demo02 extends TimerTask { private int i; public demo02(int i) { this.i = i; } @Override public void run() { System.out.println("任务被第"+i+"次执行,没有被取消"); } public static void main(String[] args) { int i=0; Calendar calendar = Calendar.getInstance(); Date time = calendar.getTime(); while(true){ i++; Timer timer = new Timer(); timer.schedule(new demo02(i),time); timer.cancel(); } }
运行结果
任务被第32412次执行,没有被取消
原因是Timer类中的cancel方法,有时抢不到任务队列的锁,而让TimerTask类中的任务正常执行
参考书籍<<java多线程编程核心技术>>高洪岩著