Timer
Timer类主要负责计划任务的功能,也就是在指定的时间开始某一个任务。
Timer类主要作用就是设置计划任务,但封装任务的类确实TimerTask类。(TimerTask是一个抽象类,所以执行计划任务的代码要放进去TimerTask的子类中)
schedule(TimerTask task,Date time)
该方法的作用是在指定的日期执行一次某一任务。
执行任务的时间晚于当前时间:在未来执行的效果
例子:
public class Schedule {
private static Timer timer=new Timer();
public static void main(String[] args) {
MyTask task=new MyTask();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime=LocalDateTime.parse("2018-10-28 19:16:00",df);
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime.atZone(zoneId);
Date date = Date.from(zdt.toInstant());
System.out.println("执行时间:"+date+",当前时间:"+new Date());
timer.schedule(task, date);
}
}
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("运行了!时间为:"+new Date());
}
}
结果:
执行时间:Sun Oct 28 19:16:00 CST 2018,当前时间:Sun Oct 28 19:15:43 CST 2018
运行了!时间为:Sun Oct 28 19:16:00 CST 2018
这样的方式是一个新的线程,并不是守护线程,所以导致就算执行完任务,但是进程还没销毁。
解决方法:
private static Timer timer=new Timer(true);
计划时间早于当前时间:提前运行的效果
例子:
/**
* @author 作者 E-mail:
* @version 创建时间:2018年10月28日 下午7:03:26
* 类说明
*/
public class Schedule {
private static Timer timer=new Timer(true);
public static void main(String[] args) {
MyTask task=new MyTask();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime=LocalDateTime.parse("2018-10-28 19:16:00",df);
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime.atZone(zoneId);
Date date = Date.from(zdt.toInstant());
System.out.println("执行时间:"+date+",当前时间:"+new Date());
timer.schedule(task, date);
}
}
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("运行了!时间为:"+new Date());
}
}
结果为:
执行时间:Sun Oct 28 19:16:00 CST 2018,当前时间:Sun Oct 28 19:18:40 CST 2018
运行了!时间为:Sun Oct 28 19:18:40 CST 2018
多个TimerTask任务及延时的测试
例子:
public class Schedule2 {
private static Timer timer=new Timer();
public static void main(String[] args) {
MyTask task1=new MyTask();
MyTask task2=new MyTask();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime1=LocalDateTime.parse("2018-10-28 19:32:30",df);
LocalDateTime localDateTime2=LocalDateTime.parse("2018-10-28 19:33:00",df);
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime1.atZone(zoneId);
Date date1 = Date.from(zdt.toInstant());
zdt = localDateTime2.atZone(zoneId);
Date date2 = Date.from(zdt.toInstant());
System.out.println("任务1:执行时间:"+date1+",当前时间:"+new Date());
System.out.println("任务2:执行时间:"+date2+",当前时间:"+new Date());
timer.schedule(task1, date1);
timer.schedule(task2, date2);
}
}
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("运行了!时间为:"+new Date());
}
}
结果:
任务1:执行时间:Sun Oct 28 19:32:30 CST 2018,当前时间:Sun Oct 28 19:32:12 CST 2018
任务2:执行时间:Sun Oct 28 19:33:00 CST 2018,当前时间:Sun Oct 28 19:32:12 CST 2018
运行了!时间为:Sun Oct 28 19:32:30 CST 2018
运行了!时间为:Sun Oct 28 19:33:00 CST 2018
TimerTask是以队列的方式一个一个被顺序执行的,所以执行的时间有可能和预期的时间不一致,因为假如前面的任务消耗的时间较长,则后面的任务运行的时间也会被延迟。
如下:
public class Schedule2 {
private static Timer timer=new Timer();
public static void main(String[] args) {
MyTask task1=new MyTask();
MyTask task2=new MyTask();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime1=LocalDateTime.parse("2018-10-28 19:37:00",df);
LocalDateTime localDateTime2=LocalDateTime.parse("2018-10-28 19:37:05",df);
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime1.atZone(zoneId);
Date date1 = Date.from(zdt.toInstant());
zdt = localDateTime2.atZone(zoneId);
Date date2 = Date.from(zdt.toInstant());
System.out.println("任务1:执行时间:"+date1+",当前时间:"+new Date());
System.out.println("任务2:执行时间:"+date2+",当前时间:"+new Date());
timer.schedule(task1, date1);
timer.schedule(task2, date2);
}
}
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("start时间为:"+new Date());
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("end时间为:"+new Date());
}
}
结果为:
任务1:执行时间:Sun Oct 28 19:37:00 CST 2018,当前时间:Sun Oct 28 19:36:30 CST 2018
任务2:执行时间:Sun Oct 28 19:37:05 CST 2018,当前时间:Sun Oct 28 19:36:30 CST 2018
start时间为:Sun Oct 28 19:37:00 CST 2018
end时间为:Sun Oct 28 19:37:20 CST 2018
start时间为:Sun Oct 28 19:37:20 CST 2018
end时间为:Sun Oct 28 19:37:40 CST 2018
schedule(TimerTask task,Date firstTime,long period)
该方法的作用是在指定的日期之后,按指定的间隔周期性地无限循环地执行某一任务
public class Schedule2 {
private static Timer timer=new Timer();
public static void main(String[] args) {
MyTask task1=new MyTask();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime1=LocalDateTime.parse("2018-10-28 19:43:00",df);
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime1.atZone(zoneId);
Date date1 = Date.from(zdt.toInstant());
System.out.println("任务1:执行时间:"+date1+",当前时间:"+new Date());
timer.schedule(task1, date1,2000);
}
}
class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("执行了!时间为:"+new Date());
}
}
结果为:
任务1:执行时间:Sun Oct 28 19:43:00 CST 2018,当前时间:Sun Oct 28 19:42:49 CST 2018
执行了!时间为:Sun Oct 28 19:43:00 CST 2018
执行了!时间为:Sun Oct 28 19:43:02 CST 2018
执行了!时间为:Sun Oct 28 19:43:04 CST 2018
执行了!时间为:Sun Oct 28 19:43:06 CST 2018
执行了!时间为:Sun Oct 28 19:43:08 CST 2018
执行了!时间为:Sun Oct 28 19:43:10 CST 2018
TimerTask的cancel()与Timer的cancel()
TimerTask的cancel()是将自身从任务队列中移除,其他任务不受影响
Timer的cancel()是全部任务都被清除,并且进程被销毁。(ps:Timer类中的cancel()方法有时争抢不到queue锁,就停止不了执行任务)
public class Schedule2 {
private static Timer timer=new Timer();
public static void main(String[] args) {
MyTask1 task1=new MyTask1();
MyTask2 task2=new MyTask2();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime1=LocalDateTime.parse("2018-10-28 19:37:00",df);
LocalDateTime localDateTime2=LocalDateTime.parse("2018-10-28 19:37:05",df);
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime1.atZone(zoneId);
Date date1 = Date.from(zdt.toInstant());
zdt = localDateTime2.atZone(zoneId);
Date date2 = Date.from(zdt.toInstant());
System.out.println("任务1:执行时间:"+date1+",当前时间:"+new Date());
System.out.println("任务2:执行时间:"+date2+",当前时间:"+new Date());
timer.schedule(task1, date1,2000);
timer.schedule(task2, date2,2000);
try {
Thread.sleep(10000);
//timer的cancel()
timer.cancel();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
class MyTask1 extends TimerTask{
@Override
public void run() {
System.out.println("MyTask1为:"+new Date());
//timerTask的cancel()
this.cancel();
}
}
class MyTask2 extends TimerTask{
@Override
public void run() {
System.out.println("MyTask2为:"+new Date());
}
}
结果:
任务1:执行时间:Sun Oct 28 19:37:00 CST 2018,当前时间:Sun Oct 28 19:49:47 CST 2018
任务2:执行时间:Sun Oct 28 19:37:05 CST 2018,当前时间:Sun Oct 28 19:49:47 CST 2018
MyTask1为:Sun Oct 28 19:49:47 CST 2018
MyTask2为:Sun Oct 28 19:49:47 CST 2018
MyTask2为:Sun Oct 28 19:49:49 CST 2018
MyTask2为:Sun Oct 28 19:49:51 CST 2018
MyTask2为:Sun Oct 28 19:49:53 CST 2018
MyTask2为:Sun Oct 28 19:49:55 CST 2018
之后就结束了,进程也销毁了。
Timer的cancel()停止不了(每次都new一次):
public class Schedule2 {
public static void main(String[] args) {
while(true){
Timer timer=new Timer();
MyTask1 task1=new MyTask1();
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime1=LocalDateTime.parse("2018-10-28 19:37:00",df);
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zdt = localDateTime1.atZone(zoneId);
Date date1 = Date.from(zdt.toInstant());
timer.schedule(task1, date1);
timer.cancel();
}
}
}
class MyTask1 extends TimerTask{
@Override
public void run() {
System.out.println("MyTask1为:"+new Date());
}
}