主要两个要点:
- 实现指定时间执行任务
- 实现按照指定周期执行任务
定时器Timer的使用
JDK中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某个任务。
Timer类的主要作用就是设置计划任务,但封装任务的类却是TimerTask类。
执行计划任务的代码要放入TaskTimer的子类中,因为TimerTask是一个抽象类。
方法schedule(TimerTask task, Date time)的测试
schedule()方法的作用是在指定的日期执行一次某任务。
public class Run1 {
/** Field timer */
private static Timer timer = new Timer();
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
try {
MyTask task = new MyTask();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = "2018-05-03 19:59:00";
Date dateRef = sdf.parse(dateString);
System.out.println("字符串时间,:" + dateRef.toLocaleString() + " 当前时间:" + new Date().toLocaleString());
timer.schedule(task, dateRef);
} catch (ParseException e) {
e.printStackTrace();
}
}
/**
* Class MyTask
*
*
* @version 1.0, 18/05/03
* @author tz
*/
public static class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("运行了,时间为:" + new Date());
}
}
}
/*result:
字符串时间,:2018-5-3 19:59:00 当前时间:2018-5-3 20:01:12
运行了,时间为:Thu May 03 20:01:12 CST 2018
*/
程序运行结束,但进程还未被销毁。
创建一个Timer就是启动一个新线程,这个新启动的线程并不是守护进程,会一直运行下去。
也可以在Timer创建时1改为守护进程。代码如下:
public class Run1TimerDaemon {
/** Field timer */
private static Timer timer = new Timer(true);
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
try {
MyTask task = new MyTask();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = "2018-05-04 08:46:00";
Date dateRef = sdf.parse(dateString);
System.out.println("字符串时间:" + dateRef.toLocaleString() + "当前时间:" + new Date().toLocaleString());
timer.schedule(task, dateRef);
} catch (ParseException e) {
e.printStackTrace();
}
}
/**
* Class MyTask
*
*
* @version 1.0, 18/05/04
* @author tz
*/
public static class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("运行了!时间为:" + new Date());
}
}
}
/*result:
字符串时间:2018-5-4 8:46:00当前时间:2018-5-4 8:46:49
*/
程序运行后迅速结束当前进程,并且TimerTask中任务不再被运行,因为进程已经结束。
如果执行任务时间早于当前时间,则立即执行task任务。
Timer中允许有多个TimerTask任务。TimerTask是以队列的方式一个一个被执行的,所以执行那个时间爱你有可能和预期时间不一致,因为前面的任务有可能消耗较长时间。
public class Run2Later {
/** Field timer */
private static Timer timer = new Timer();
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
try {
MyTask1 task1 = new MyTask1();
MyTask2 task2 = new MyTask2();
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString1 = "2018-05-04 14:30:00";
String dateString2 = "2018-05-04 14:32:00";
Date dateRef1 = sdf1.parse(dateString1);
Date dateRef2 = sdf2.parse(dateString2);
System.out.println("字符串1时间:" + dateRef1.toLocaleString() + " 当前时间:" + new Date());
System.out.println("字符串2时间:" + dateRef2.toLocaleString() + " 当前时间:" + new Date());
timer.schedule(task1, dateRef1);
timer.schedule(task2, dateRef2);
} catch (ParseException e) {
e.printStackTrace();
}
}
/**
* Class MyTask1
*
*
* @version 1.0, 18/05/04
* @author tz
*/
public static class MyTask1 extends TimerTask {
@Override
public void run() {
try {
System.out.println("1 begin 运行了,时间为:" + new Date());
Thread.sleep(20000);
System.out.println("1 end 运行了,时间为" + new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* Class MyTask2
*
*
* @version 1.0, 18/05/04
* @author tz
*/
public static class MyTask2 extends TimerTask {
@Override
public void run() {
System.out.println("2 begin 运行了,时间为:" + new Date());
System.out.println("2 运行了,运行时间为:" + new Date());
System.out.println("2 end 运行了,时间为" + new Date());
}
}
}
/*result:
字符串1时间:2018-5-4 14:30:00 当前时间:Fri May 04 14:37:59 CST 2018
字符串2时间:2018-5-4 14:32:00 当前时间:Fri May 04 14:37:59 CST 2018
1 begin 运行了,时间为:Fri May 04 14:37:59 CST 2018
1 end 运行了,时间为Fri May 04 14:38:19 CST 2018
2 begin 运行了,时间为:Fri May 04 14:38:19 CST 2018
2 运行了,运行时间为:Fri May 04 14:38:19 CST 2018
2 end 运行了,时间为Fri May 04 14:38:19 CST 2018
*/
方法schedule(TimerTask task, Date firstTime, long period)
该方法的作用是在指定日期之后,按指定的间隔周期性的无限循环某一任务。
public class Run {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
try {
MyTask task = new MyTask();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = "2018-05-04 14:48:00";
Timer timer = new Timer();
Date dateRef = sdf.parse(dateString);
System.out.println("字符串时间:" + dateRef.toLocaleString() + " 当前时间:" + new Date().toLocaleString());
timer.schedule(task, dateRef, 4000);
} catch (ParseException e) {
e.printStackTrace();
}
}
/**
* Class MyTask
*
*
* @version 1.0, 18/05/04
* @author tz
*/
public static class MyTask extends TimerTask {
@Override
public void run() {
System.out.println("运行了! 时间为:" + new Date());
}
}
}
/*result:
字符串时间:2018-5-4 14:48:00 当前时间:2018-5-4 14:53:30
运行了! 时间为:Fri May 04 14:53:30 CST 2018
运行了! 时间为:Fri May 04 14:53:34 CST 2018
运行了! 时间为:Fri May 04 14:53:38 CST 2018
运行了! 时间为:Fri May 04 14:53:42 CST 2018
*/
task以周期为4s的状态下一直运行。
TimerTask的cancel方法
TimerTask的cancel方法是将自身从任务队列中清除掉。
public class Run2 {
/**
* Method main
*
*
* @param args
*/
public static void main(String[] args) {
try {
MyTaskA task1 = new MyTaskA();
MyTaskB task2 = new MyTaskB();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = "2018-05-04 14:48:00";
Timer timer = new Timer();
Date dateRef = sdf.parse(dateString);
System.out.println("字符串时间:" + dateRef.toLocaleString() + " 当前时间:" + new Date().toLocaleString());
timer.schedule(task1, dateRef, 4000);
timer.schedule(task2, dateRef, 4000);
} catch (ParseException e) {
e.printStackTrace();
}
}
/**
* Class MyTask
*
*
* @version 1.0, 18/05/04
* @author tz
*/
public static class MyTaskA extends TimerTask {
@Override
public void run() {
System.out.println("A 运行了! 时间为:" + new Date());
this.cancel();
}
}
/**
* Class MyTaskB
*
*
* @version 1.0, 18/05/04
* @author tz
*/
public static class MyTaskB extends TimerTask {
@Override
public void run() {
System.out.println("B 运行了! 时间为:" + new Date());
}
}
}
/*result:
字符串时间:2018-5-4 14:48:00 当前时间:2018-5-4 15:10:18
A 运行了! 时间为:Fri May 04 15:10:18 CST 2018
B 运行了! 时间为:Fri May 04 15:10:18 CST 2018
B 运行了! 时间为:Fri May 04 15:10:22 CST 2018
B 运行了! 时间为:Fri May 04 15:10:26 CST 2018
B 运行了! 时间为:Fri May 04 15:10:30 CST 2018
*/
Timer的cancel方法
Timer的cancel方法是清除所有的任务队列。
因为Timer的cancel()方法有时候并没有争抢到队列锁,所以TimerTask类中的任务会继续正常执行。
方法schedule(TimerTask task, long delay, long period)
该方法的作用是执行schedule(TimerTask task, long delay, long period)方法当前的时间为参考时间,在此时间的基础上延迟指定的毫秒数,再以某一时间间隔无限制的执行下去。
凡是方法中带有period参数的,都是无限循环执行TimerTask任务。
方法scheduleFixRate(TimerTask task, Date firstTime, long period)
方法scheduleFixRate(TimerTask task, Date firstTime, long period)和schedule()的区别在于不延时的情况。
使用schedule方法,如果执行任务的时间没有延迟,但下一任务的执行时间参考的是上一次任务的“开始”时间。
使用scheduleFixRate方法,参考的则是上一任务的“结束”时间。
网友评论