博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java多线程编程(五)定时器Timer
阅读量:4670 次
发布时间:2019-06-09

本文共 27468 字,大约阅读时间需要 91 分钟。

  一、定时器Timer的使用

  在JDK库中Timer类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务。Timer类的主要作用就是设置计划任务,但封装任务的类确实TimerTask类,执行计划任务的代码要放入TimerTask类的子类中,因为TimerTask是一个抽象类。

  

  1.方法schedule(TimerTask task,Date time)的测试

  该方法的任务是在指定的日期执行一次某一任务。

  (1)执行任务的时间晚于当前时间:在未来执行的效果

  示例:从输出结果可以看出,设定执行时间在29分钟,然后等待了47秒后,MyTask类里面的run()方法才执行。

package test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run1 {    private static Timer timer = new Timer();    static public class MyTask extends TimerTask {        @Override        public void run() {            System.out.println("运行了!时间为:" + new Date());        }    }    public static void main(String[] args) {        try {            MyTask task = new MyTask();            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString = "2018-5-7 17:29:00";            Date dateRef = sdf.parse(dateString);            System.out.println("字符串时间:" + dateRef.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.schedule(task, dateRef);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串时间:2018-5-7 17:29:00 当前时间:2018-5-7 17:28:13 运行了!时间为:Mon May 07 17:29:00 GMT+08:00 2018

   虽然程序执行完了,但是进程还未销毁,仍然处于执行状态,这是因为,在new Timer()对象时,实际的构造方法是这样的:

public Timer() {        this("Timer-" + serialNumber());    }
public Timer(String name) {        thread.setName(name);        thread.start();    }

  从构造方法可以看出,创建一个Timer对象就是启动一个新的线程,这个新启动的线程并不是守护线程,它一直在运行。

  示例2:将private static Timer timer = new Timer();声明修改成private static Timer timer = new Timer(true);即让新创建的Timer改成守护线程,还是查看Timer()构造函数:

 

public Timer(boolean isDaemon) {        this("Timer-" + serialNumber(), isDaemon);    }

 

public Timer(String name, boolean isDaemon) {        thread.setName(name);        thread.setDaemon(isDaemon);        thread.start();    }

  通过将新启动的线程设置为守护线程,就可以实现程序运行后迅速结束当前的进程,而且TimerTask中的任务也不再被运行,因为进程已经结束了,守护进程在进程开始前就已经创建了,当然没有检测到有进程在执行状态,所以就退出了。

字符串时间:2018-5-7 17:32:00 当前时间:2018-5-7 17:31:18

 

  (2)计划时间早于当前时间:提前运行的效果

  如果执行任务的时间早于当前时间,则立即执行task任务。

  示例:从设置执行任务的时间在当前时间的前一分钟,通过输出可以看出,task任务立刻执行了。

字符串时间:2018-5-7 17:32:00 当前时间:2018-5-7 17:33:15运行了!时间为:Mon May 07 17:33:15 GMT+08:00 2018

   (3)多个TimerTask任务及延时的测试

  示例1:TimerTask任务是以队列的方式一个一个被顺序执行的,所以执行的时间有可能和预期的时间不一致,因为前面的任务有可能消耗的时间比较长,则后面的任务运行的时间也会被延迟。

package test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run2 {    private static Timer timer = new Timer();    static public class MyTask1 extends TimerTask {        @Override        public void run() {            System.out.println("运行了!时间为:" + new Date());        }    }    static public class MyTask2 extends TimerTask {        @Override        public void run() {            System.out.println("运行了!时间为:" + new Date());        }    }    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-5-7 17:36:00";            String dateString2 = "2018-5-7 17:36:10";            Date dateRef1 = sdf1.parse(dateString1);            Date dateRef2 = sdf2.parse(dateString2);            System.out.println("字符串1时间:" + dateRef1.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            System.out.println("字符串2时间:" + dateRef2.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.schedule(task1, dateRef1);            timer.schedule(task2, dateRef2);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串1时间:2018-5-7 17:36:00 当前时间:2018-5-7 17:35:33字符串2时间:2018-5-7 17:36:10 当前时间:2018-5-7 17:35:33运行了!时间为:Mon May 07 17:36:00 GMT+08:00 2018运行了!时间为:Mon May 07 17:36:10 GMT+08:00 2018

   示例2:由于task1线程运行时间需要20秒的时间,因此影响了task2的执行时间,所以在task1任务执行完之后马上执行了task2任务。

package test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run2Later {    private static Timer timer = new Timer();    static public 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();            }        }    }    static public class MyTask2 extends TimerTask {        @Override        public void run() {            System.out.println("2 begin 运行了!时间为:" + new Date());            System.out.println("运行了!时间为:" + new Date());            System.out.println("2   end 运行了!时间为:" + new Date());        }    }    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-5-7 17:40:00";            String dateString2 = "2018-5-7 17:40:10";            Date dateRef1 = sdf1.parse(dateString1);            Date dateRef2 = sdf2.parse(dateString2);            System.out.println("字符串1时间:" + dateRef1.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            System.out.println("字符串2时间:" + dateRef2.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.schedule(task1, dateRef1);            timer.schedule(task2, dateRef2);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串1时间:2018-5-7 17:40:00 当前时间:2018-5-7 17:39:16字符串2时间:2018-5-7 17:40:10 当前时间:2018-5-7 17:39:161 begin 运行了!时间为:Mon May 07 17:40:00 GMT+08:00 20181   end 运行了!时间为:Mon May 07 17:40:20 GMT+08:00 20182 begin 运行了!时间为:Mon May 07 17:40:20 GMT+08:00 2018运行了!时间为:Mon May 07 17:40:20 GMT+08:00 20182   end 运行了!时间为:Mon May 07 17:40:20 GMT+08:00 2018

  2.方法schedule(TimerTask task,Date firstTime,long period)的测试

  该方法的作用是在指定的日期之后,按指定的间隔周期性地无线循环地执行某一任务。

  (1)计划时间晚于当前时间:在未来执行的效果

  示例:从输出结果可以看出,在指定的时间开始运行任务,并且每隔4秒运行一次。

package test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run {    static public class MyTask extends TimerTask {        @Override        public void run() {            System.out.println("运行了!时间为:" + new Date());        }    }    public static void main(String[] args) {        try {            MyTask task = new MyTask();            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString = "2018-5-7 17:45: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();        }    }}
字符串时间:2018-5-7 17:45:00 当前时间:2018-5-7 17:44:24运行了!时间为:Mon May 07 17:45:00 GMT+08:00 2018运行了!时间为:Mon May 07 17:45:04 GMT+08:00 2018运行了!时间为:Mon May 07 17:45:08 GMT+08:00 2018运行了!时间为:Mon May 07 17:45:12 GMT+08:00 2018 ...

   (2)计划时间早于当前时间:提前运行的效果

  示例:计划时间早于当前时间,会立即执行task任务。

字符串时间:2018-5-7 17:45:00 当前时间:2018-5-7 17:46:24运行了!时间为:Mon May 07 17:46:24 GMT+08:00 2018运行了!时间为:Mon May 07 17:46:28 GMT+08:00 2018运行了!时间为:Mon May 07 17:46:32 GMT+08:00 2018运行了!时间为:Mon May 07 17:46:36 GMT+08:00 2018...

   (3)任务执行时间被延时

  示例:设置一个任务执行时间为5秒,但是间隔只有4秒,这种情况下,任务被延时,但还是一个一个按顺序运行。

package test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run2_1 {    static public class MyTaskA extends TimerTask {        @Override        public void run() {            try {                System.out.println("A运行了!时间为:" + new Date());                Thread.sleep(5000);                System.out.println("A结束了!时间为:" + new Date());            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) {        try {            MyTaskA taskA = new MyTaskA();            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString = "2018-5-7 17:49:00";            Timer timer = new Timer();            Date dateRef = sdf.parse(dateString);            System.out.println("字符串时间:" + dateRef.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.schedule(taskA, dateRef, 4000);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串时间:2018-5-7 17:49:00 当前时间:2018-5-7 17:48:09A运行了!时间为:Mon May 07 17:49:00 GMT+08:00 2018A结束了!时间为:Mon May 07 17:49:05 GMT+08:00 2018A运行了!时间为:Mon May 07 17:49:05 GMT+08:00 2018A结束了!时间为:Mon May 07 17:49:10 GMT+08:00 2018A运行了!时间为:Mon May 07 17:49:10 GMT+08:00 2018A结束了!时间为:Mon May 07 17:49:15 GMT+08:00 2018...

   (4)TimerTask类的cancel()方法

  TimerTask类的cancel()方法的作用是将自身从任务队列中清除。

  示例:从输出可以看出,任务A在执行一次后,把自己从任务队列中清除了。(如果计划时间早于当前时间会有问题!)

package test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run2 {    static public class MyTaskA extends TimerTask {        @Override        public void run() {            System.out.println("A运行了!时间为:" + new Date());            this.cancel();        }    }    static public class MyTaskB extends TimerTask {        @Override        public void run() {            System.out.println("B运行了!时间为:" + new Date());        }    }    public static void main(String[] args) {        try {            MyTaskA taskA = new MyTaskA();            MyTaskB taskB = new MyTaskB();            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString = "2018-5-7 17:49:00";            Timer timer = new Timer();            Date dateRef = sdf.parse(dateString);            System.out.println("字符串时间:" + dateRef.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.schedule(taskA, dateRef, 4000);            timer.schedule(taskB, dateRef, 4000);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串时间:2018-5-7 17:54:00 当前时间:2018-5-7 17:53:23A运行了!时间为:Mon May 07 17:54:00 GMT+08:00 2018B运行了!时间为:Mon May 07 17:54:00 GMT+08:00 2018B运行了!时间为:Mon May 07 17:54:04 GMT+08:00 2018B运行了!时间为:Mon May 07 17:54:08 GMT+08:00 2018B运行了!时间为:Mon May 07 17:54:12 GMT+08:00 2018B运行了!时间为:Mon May 07 17:54:16 GMT+08:00 2018B运行了!时间为:Mon May 07 17:54:20 GMT+08:00 2018...

   (5)Timer类的cancel()方法

  Timer类的cancel()方法的作用是将任务队列中的全部任务清空。

  示例:任务A执行一次后,调用timer.cancel();将任务队列中的全部任务清空,并且结束了进程,进程被销毁了。

package test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run3 {    private static Timer timer = new Timer();    static public class MyTaskA extends TimerTask {        @Override        public void run() {            System.out.println("A运行了!时间为:" + new Date());            timer.cancel();        }    }    static public class MyTaskB extends TimerTask {        @Override        public void run() {            System.out.println("B运行了!时间为:" + new Date());        }    }    public static void main(String[] args) {        try {            MyTaskA taskA = new MyTaskA();            MyTaskB taskB = new MyTaskB();            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString = "2018-5-7 17:57:00";            Date dateRef = sdf.parse(dateString);            System.out.println("字符串时间:" + dateRef.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.schedule(taskA, dateRef, 4000);            timer.schedule(taskB, dateRef, 4000);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串时间:2018-5-7 17:57:00 当前时间:2018-5-7 17:56:28A运行了!时间为:Mon May 07 17:57:00 GMT+08:00 2018

   (6)Timer类的cancel()方法注意事项

  Timer类的cancel()方法有时并不一定会停止执行计划任务,而是正常执行。

  示例:这是因为Timer类中的cancel()方法有时并没有争抢到queue锁,所以TimerTask类中的任务继续正常执行,结果中输出的数也不是连续的,也可以说明这一点。

package test;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run4 {    static int i = 0;    static public class MyTask extends TimerTask {        @Override        public void run() {            System.out.println("正常执行了" + i);        }    }    public static void main(String[] args) {        while (true) {            try {                i++;                Timer timer = new Timer();                MyTask task = new MyTask();                SimpleDateFormat sdf = new SimpleDateFormat(                        "yyyy-MM-dd HH:mm:ss");                String dateString = "2018-5-7 18:05:00";                Date dateRef = sdf.parse(dateString);                timer.schedule(task, dateRef);                timer.cancel();            } catch (ParseException e) {                e.printStackTrace();            }        }    }}
正常执行了541099正常执行了592127正常执行了655574正常执行了809347正常执行了834669...

  3.方法schedule(TimerTask task,long delay)的测试

  该方法的作用是以执行schedule(TimerTask task,long delay)方法当前的时间为参考时间,在此时间基础上延迟指定的毫秒数后执行一次TimerTask任务。

  示例:在执行完方法后,延迟7秒的时间,执行了task任务。

package test;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run {    static public class MyTask extends TimerTask {        @Override        public void run() {            System.out.println("运行了!时间为:" + new Date());        }    }    public static void main(String[] args) {        MyTask task = new MyTask();        Timer timer = new Timer();        System.out.println("当前时间:" + new Date().toLocaleString());        timer.schedule(task, 7000);    }}
当前时间:2018-5-7 18:10:57运行了!时间为:Mon May 07 18:11:04 GMT+08:00 2018

  4.方法schedule(TimerTask task,long delay,long period)的测试

  该方法的作用是一执行schedule(TimerTask task,long delay,long period)方法未当前时间的参考时间,在此基础上延迟指定的毫秒数,并以某一时间间隔无限次数执行某一任务。

  示例:在执行方法后的3秒时开始以5秒为间隔无限次数执行task任务。

package test;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run {    static public class MyTask extends TimerTask {        @Override        public void run() {            System.out.println("运行了!时间为:" + new Date());        }    }    public static void main(String[] args) {            MyTask task = new MyTask();            Timer timer = new Timer();            System.out.println("当前时间:"+new Date().toLocaleString());            timer.schedule(task, 3000,5000);    }}
当前时间:2018-5-7 18:14:39运行了!时间为:Mon May 07 18:14:42 GMT+08:00 2018运行了!时间为:Mon May 07 18:14:47 GMT+08:00 2018运行了!时间为:Mon May 07 18:14:52 GMT+08:00 2018运行了!时间为:Mon May 07 18:14:57 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:02 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:07 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:12 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:17 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:22 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:27 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:32 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:37 GMT+08:00 2018运行了!时间为:Mon May 07 18:15:42 GMT+08:00 2018...

  5.方法scheduleAtFixedRate(TimerTask task,Date firstTime,long period)的测试

   方法schedule和方法scheduleAtFixedRate都会按顺序执行,所以不要考虑非线程安全的情况。  

  方法schedule和方法scheduleAtFixedRate主要的区别只在于不延时的情况。

  使用schedule方法:如果执行任务的时间没有被延时,那么下一次任务的执行时间参考的是上一次任务的“开始”时的时间来计算的。

  使用scheduleAtFixedRate方法:如果执行任务的时间没有被延时,那么下一次任务的执行时间参考的是上一次任务的“结束”时的时间来计算的。  

  延时的情况,则没有区别,都是下一次任务的执行时间参考的是上一次任务的“结束”时的时间来计算的。

  (1)schedule方法任务不延时

  示例:从输出结果可以看出,线程sleep的时间1000小于设置的时间间隔3000,因此不存在延时,在这种情况下,两次begin的时间间隔就是3秒。

package test.run;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run1 {    private static Timer timer = new Timer();    private static int runCount = 0;    static public class MyTask1 extends TimerTask {        @Override        public void run() {            try {                System.out.println("1 begin 运行了!时间为:" + new Date());                Thread.sleep(1000);                System.out.println("1   end 运行了!时间为:" + new Date());                runCount++;                if (runCount == 5) {                    timer.cancel();                }            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) {        try {            MyTask1 task1 = new MyTask1();            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString1 = "2018-5-7 18:22:00";            Date dateRef1 = sdf1.parse(dateString1);            System.out.println("字符串1时间:" + dateRef1.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.schedule(task1, dateRef1, 3000);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串1时间:2018-5-7 18:22:00 当前时间:2018-5-7 18:21:151 begin 运行了!时间为:Mon May 07 18:22:00 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:22:01 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:22:03 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:22:04 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:22:06 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:22:07 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:22:09 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:22:10 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:22:12 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:22:13 GMT+08:00 2018

   (2)schedule方法任务延时

  示例:修改run方法中的sleep为5000>时间间隔设置2000,则从输出结果可以看出,下一次的begin的时间是上一次end的时间。

字符串1时间:2018-5-7 18:26:00 当前时间:2018-5-7 18:25:401 begin 运行了!时间为:Mon May 07 18:26:00 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:26:05 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:26:05 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:26:10 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:26:10 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:26:15 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:26:15 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:26:20 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:26:20 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:26:25 GMT+08:00 2018

   (3)scheduleAtFixedRate方法任务不延时

  示例1:sleep值为2000<时间间隔设置3000(且字符串时间要先于当前时间才可以),则从输出结果可以看出,如果执行任务的时间没有被延时,则这一次的begin和这一次的end之间相差时间间隔设置3000,而这一次的end和下一次的begin时间是一致的。

package test.run;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run3 {    private static Timer timer = new Timer();    private static int runCount = 0;    static public class MyTask1 extends TimerTask {        @Override        public void run() {            try {                System.out.println("1 begin 运行了!时间为:" + new Date());                Thread.sleep(2000);                System.out.println("1   end 运行了!时间为:" + new Date());                runCount++;                if (runCount == 5) {                    timer.cancel();                }            } catch (InterruptedException e) {                e.printStackTrace();            }        }    }    public static void main(String[] args) {        try {            MyTask1 task1 = new MyTask1();            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString1 = "2018-5-7 18:32:00";            Date dateRef1 = sdf1.parse(dateString1);            System.out.println("字符串1时间:" + dateRef1.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.scheduleAtFixedRate(task1, dateRef1, 3000);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串1时间:2018-5-7 18:32:00 当前时间:2018-5-7 20:17:12 1 begin 运行了!时间为:Mon May 07 20:17:12 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 20:17:15 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 20:17:15 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 20:17:17 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 20:17:17 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 20:17:19 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 20:17:19 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 20:17:21 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 20:17:21 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 20:17:23 GMT+08:00 2018

   示例2:字符串时间晚于当前时间的情况下,这种情况下,竟然是和schedule的不延时的情况是一致的。(这块很绕,就很气!应该是分了两种情况吧,具体实现看源码吧!)

字符串1时间:2018-5-7 20:32:00 当前时间:2018-5-7 20:31:171 begin 运行了!时间为:Mon May 07 20:32:00 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:32:02 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:32:03 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:32:05 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:32:06 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:32:08 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:32:09 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:32:11 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:32:12 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:32:14 GMT+08:00 2018

  (4)scheduleAtFixedRate方法任务延时

  示例:sleep值5000>时间间隔设置2000,则从输出结果可以看出,如果执行任务的时间被延时,那么下一次任务的执行时间以上一次任务“结束”时的时间为参考来计算。

字符串1时间:2018-5-7 18:37:00 当前时间:2018-5-7 18:36:421 begin 运行了!时间为:Mon May 07 18:37:00 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:37:05 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:37:05 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:37:10 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:37:10 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:37:15 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:37:15 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:37:20 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 18:37:20 GMT+08:00 20181   end 运行了!时间为:Mon May 07 18:37:25 GMT+08:00 2018

   (5)schedule方法不具有追赶执行性

  示例:时间37:00:到40:47所对应的task任务被取消了,不执行了,这就是task任务不追赶的情况。

package test.run;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run5 {    private static Timer timer = new Timer();    static public class MyTask1 extends TimerTask {        @Override        public void run() {                System.out.println("1 begin 运行了!时间为:" + new Date());                System.out.println("1   end 运行了!时间为:" + new Date());        }    }    public static void main(String[] args) {        try {            MyTask1 task1 = new MyTask1();            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString1 = "2018-5-7 18:37:00";            Date dateRef1 = sdf1.parse(dateString1);            System.out.println("字符串1时间:" + dateRef1.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.schedule(task1, dateRef1, 5000);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串1时间:2018-5-7 18:37:00 当前时间:2018-5-7 18:40:47 1 begin 运行了!时间为:Mon May 07 18:40:47 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 18:40:47 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 18:40:52 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 18:40:52 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 18:40:57 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 18:40:57 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 18:41:02 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 18:41:02 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 18:41:07 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 18:41:07 GMT+08:00 2018 1 begin 运行了!时间为:Mon May 07 18:41:12 GMT+08:00 2018 1   end 运行了!时间为:Mon May 07 18:41:12 GMT+08:00 2018 ...

   (6)scheduleAtFixedRate方法具有追赶性

  示例:从输出结果可以看出,在20:25:43时刻,task1任务执行了很多次之后才按照正常的时间间隔执行,这是由于为了补充两个时间段之间的task1任务,所以就被“补充性”地执行了,这就是Task任务追赶执行的特性。

package test.run;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Timer;import java.util.TimerTask;public class Run6 {    private static Timer timer = new Timer();    static public class MyTask1 extends TimerTask {        @Override        public void run() {                System.out.println("1 begin 运行了!时间为:" + new Date());                System.out.println("1   end 运行了!时间为:" + new Date());        }    }    public static void main(String[] args) {        try {            MyTask1 task1 = new MyTask1();            SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            String dateString1 = "2018-5-7 20:24:00";            Date dateRef1 = sdf1.parse(dateString1);            System.out.println("字符串1时间:" + dateRef1.toLocaleString() + " 当前时间:"                    + new Date().toLocaleString());            timer.scheduleAtFixedRate(task1, dateRef1, 5000);        } catch (ParseException e) {            e.printStackTrace();        }    }}
字符串1时间:2018-5-7 20:24:00 当前时间:2018-5-7 20:25:431 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:43 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:45 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:45 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:50 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:50 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:25:55 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:25:55 GMT+08:00 20181 begin 运行了!时间为:Mon May 07 20:26:00 GMT+08:00 20181   end 运行了!时间为:Mon May 07 20:26:00 GMT+08:00 2018 ...

 

转载于:https://www.cnblogs.com/BigJunOba/p/8991341.html

你可能感兴趣的文章
架构师软技能之协商(上)
查看>>
商品翻牌效果(纯css)
查看>>
win10 UWP 序列化
查看>>
读书心得
查看>>
前端知识整理 CSS盒模型
查看>>
sendmail 常见报错总结
查看>>
asp.net Response.AddHeader的方法来下载
查看>>
neo4j-访问提示No authorization header supplied.
查看>>
android-activity生命周期方法
查看>>
基于贪心算法的几类区间覆盖问题 nyoj 12喷水装置(二) nyoj 14会场安排问题...
查看>>
web之JavaScript
查看>>
HTML input 控件
查看>>
MongoDB副本集配置系列六:定位MongoDB慢的原因
查看>>
[EGORefreshTableHeaderView]手动启动下拉更新的方法
查看>>
Linux磁盘分区/格式化/挂载目录
查看>>
raspberry pi下使用mp3blaster播放mp3音乐
查看>>
[转]win7 64位下android开发环境的搭建
查看>>
mysql 无法链接, 输入密码失败
查看>>
java中enum类型的使用
查看>>
枚举类型转换成字符串
查看>>