概述
Timer类的主要作用是设置计划任务,但封装任务的类却是TimerTask类。执行计划任务的代码要放入TimerTask的子类中,因为TimerTask是一个抽象类。
方法schedule(task, delay)使用
schedule(task, delay)表示在将来的某个时间执行计划任务。
1 /** 2 * 任务类 3 * @author ko 4 * 5 */ 6 public class MyTask extends TimerTask { 7 @Override 8 public void run() { 9 System.out.println("get last info..."+new Date().toString()); 10 } 11 }
1 /** 2 * 测试类 3 * @author ko 4 * 5 */ 6 public class Test { 7 public static void main(String[] args) { 8 Timer timer = new Timer(); 9 Calendar calendar = Calendar.getInstance(); 10 calendar.add(Calendar.SECOND, 3); 11 System.out.println("1 "+new Date().toString()); 12 timer.schedule(new MyTask(), calendar.getTime()); 13 } 14 }
在3s后执行计划任务,虽然结果打印正确,但是红色按钮却一直亮着,代表线程还在运行,那这是怎么回事?
那是因为new一个TimerTask就是开一个线程,这个线程不是守护线程,会一直运行,可以改成守护线程
Timer timer = new Timer(true);
程序立马执行,但是计划任务不执行了。
如果计划执行的时间在当前时间之前,那么任务会立即执行
如果有多个TimerTask在用一个Timer下要执行,那么TimerTask不一定会按计划的时间执行,因为前面的task耗时可能会超过下一个任务执行的时间
1 /** 2 * 测试类 3 * @author ko 4 * 5 */ 6 public class Test { 7 public static void main(String[] args) { 8 Timer timer = new Timer(false); 9 Calendar calendar = Calendar.getInstance(); 10 calendar.add(Calendar.SECOND, 3); 11 System.out.println("1 "+new Date().toString()); 12 timer.schedule(new MyTask(), calendar.getTime()); 13 timer.schedule(new MyTask(), calendar.getTime()); 14 } 15 }
1 /** 2 * 任务类 3 * @author ko 4 * 5 */ 6 public class MyTask extends TimerTask { 7 @Override 8 public void run() { 9 System.out.println("get last info..."+new Date().toString()); 10 System.out.println("要耗时5s..."); 11 try { 12 Thread.sleep(5000); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 } 17 }
schedule(new MyTask(), calendar.getTime(), 3000)
在某个时间点执行计划任务,并且之后每隔Xs再次执行。
1 /** 2 * 测试类 3 * @author ko 4 * 5 */ 6 public class Test { 7 public static void main(String[] args) { 8 Timer timer = new Timer(false); 9 Calendar calendar = Calendar.getInstance(); 10 calendar.add(Calendar.SECOND, 3); 11 System.out.println("1 "+new Date().toString()); 12 timer.schedule(new MyTask(), calendar.getTime(), 3000); 13 } 14 }
1 /** 2 * 任务类 3 * @author ko 4 * 5 */ 6 public class MyTask extends TimerTask { 7 @Override 8 public void run() { 9 System.out.println("get last info..."+new Date().toString()); 10 } 11 }
TaskTimer的cancel()方法使用
该方法会将自身从任务队列中清楚,需要注意的是如果该方法执行的时候,任务正在执行的话,不会立即终止任务,而是会等本次任务执行完,不再启动下次任务。
1 /** 2 * 测试类 3 * @author ko 4 */ 5 public class Test { 6 public static void main(String[] args) { 7 Timer timer = new Timer(false); 8 Calendar calendar = Calendar.getInstance(); 9 calendar.add(Calendar.SECOND, 3); 10 11 MyTask t1 = new MyTask("t1"); 12 timer.schedule(t1, calendar.getTime(),1000); 13 MyTask t2 = new MyTask("t2"); 14 timer.schedule(t2, calendar.getTime(),1000); 15 16 try { 17 Thread.sleep(5000); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 t1.cancel(); 22 } 23 }
1 /** 2 * 任务类 3 * @author ko 4 * 5 */ 6 public class MyTask extends TimerTask { 7 protected String tName; 8 9 public MyTask(String tName) { 10 super(); 11 this.tName = tName; 12 } 13 14 @Override 15 public void run() { 16 System.out.println(tName + " get last info..."+new Date().toString()); 17 } 18 }
可以看到执行t1任务被终止了。
Timer的cancel()方法使用
该方法会终止任务队列里的所有任务。
把上面代码的t1.cancel()换成timer.cancel()测试。
可以看到所有任务都被终止了。
scheduleAtFixedRate(task, delay, period)方法使用
scheduleAtFixedRate和schedule一样都会按顺序执行,所以不需要考虑非线程安全的情况。
scheduleAtFixedRate和schedule的区别只体现在不延时的情况下。
在不延时的情况下,schedule 下一次任务执行的时间参考的是上一次任务“开始”的时间。scheduleAtFixedRate下一次任务执行的时间参考的是上一次任务“结束”的时间。
在延迟的情况下,scheduleAtFixedRate和schedule都是参考的上一次任务“结束”的时间。