在执行定时任务的时候可以用Timer来实现,现在小编对学到的进行一次总结,先来看一个demo
1 public class TimerTest {
2
3 public static void main(String[] args) throws ParseException {
4 Date date=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:18:00");
5 new Timer().schedule(new TimerTask() {
6 @Override
7 public void run() {
8 System.out.println(new Date().getSeconds()+" 执行");
9 }
10 }, date);
11 }
12 }
这段代码的意思是,先建一个Timer,Timer开始执行的时间是” 2017-08-17 11:18:00”。
Timer重复执行
上述代码Timer只会执行一次,如果我们想让定时任务每隔一段时间就执行呢?此时可以用Timer提供的schedule方法的另一个重载 public void schedule(TimerTask task, long delay, long period)。意思是Timer在delay的时候开始执行,每隔period时间长度执行一次。
1 public class TimerTest {
2
3 public static void main(String[] args) throws ParseException {
4 Date date=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:18:00");
5 new Timer().schedule(new TimerTask() {
6 @Override
7 public void run() {
8 System.out.println(new Date().getSeconds()+" 执行");
9 }
10 }, date,1000);
11 }
12 }
执行结果
37 执行
38 执行
39 执行
40 执行
……
Timer执行延时
在执行TimerTask的时候可能会出现线程执行时间过长的情况,超过了Timer的等待时间。此时会是什么情况呢?
1 public class TimerTest { 2 3 public static void main(String[] args) throws ParseException { 4 Date date=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:18:00"); 5 new Timer().schedule(new TimerTask() { 6 @Override 7 public void run() { 8 System.out.println(new Date().getSeconds()+" 开始执行"); 9 try { 10 Thread.sleep(2000); 11 System.out.println(new Date().getSeconds()+" 执行结束"); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 } 16 }, date,1000); 17 } 18 }
看执行结果
0 开始执行
2 执行结束
2 开始执行
4 执行结束
4 开始执行
6 执行结束
6 开始执行
8 执行结束
8 开始执行
scheduleAtFixedRate
使用schedule方法执行Timer任务,如果开始的时间是在当前时间之前,Timer并不会对之前没有执行的任务进行补充执行。也就是延时之后,那么Timer就从当前时间开始接着按照间隔时间执行。但是有时候我们的需求更加关注的执行的频率,需要把因为延时而导致没有执行的任务补充回来,此时就需要用到scheduleAtFiexdRate。
1 public class TimerTest { 2 3 public static void main(String[] args) throws ParseException { 4 final Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:52:00"); 5 new Timer().scheduleAtFixedRate(new TimerTask() { 6 @Override 7 public void run() { 8 System.out.println(date); 9 System.out.println(new Date().getSeconds() + " 开始执行"); 10 System.out.println("执行了"); 11 System.out.println(new Date().getSeconds() + " 执行结束"); 12 13 } 14 }, date, 10000); 15 } 16 }
执行结果
39 开始执行
执行了
39 执行结束
Thu Aug 17 11:52:00 CST 2017
39 开始执行
执行了
39 执行结束
Thu Aug 17 11:52:00 CST 2017
40 开始执行
执行了
40 执行结束
通过执行结果可以看出来,scheduleAtFixedRate上来就先将缺失的执行补上,然后再开始按照间隔时间一次一次执行。
将Timer设置成守护线程
1 public class TimerTest { 2 3 public static void main(String[] args) throws ParseException { 4 final Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2017-08-17 11:52:00"); 5 Timer timer=new Timer(); 6 TimerTask timerTask= new TimerTask() { 7 @Override 8 public void run() { 9 System.out.println(date); 10 System.out.println(new Date().getSeconds() + " 开始执行"); 11 System.out.println("执行了"); 12 System.out.println(new Date().getSeconds() + " 执行结束"); 13 14 } 15 }; 16 timer.schedule(timerTask, date); 17 } 18 }
在执行完代码之后,程序仍然在运行。看Timer.class的源代码可以发现Timer是创建了一个新的线程,而持续跟踪代码发现,新的线程进行了一个while(true)循环,再其中进入了等待状态。
1 public Timer(String name) { 2 thread.setName(name); 3 thread.start(); 4 }
解决办法
将Timer设置成守护线程,Timer有个构造函数。
1 public Timer(boolean isDaemon) { 2 this("Timer-" + serialNumber(), isDaemon); 3 }
所以我们在将new Timer()改为new Timer(true)即可。
TimerTask和Timer的cancel方法
TimerTask的cancel方法是关闭这个任务,Timer的cancel方法是关闭整个Timer。
Timer的执行实际上是启动了一个线程然后,线程中维护了一个队列,然后把TimerTask放入队列中。TimerTask的cancel方法就是将自身从任务队列中移除。Timer的cancel方法,是将队列中的任务全部清空。