美文网首页
Timer定时器

Timer定时器

作者: onlyHalfSoul | 来源:发表于2018-05-25 15:08 被阅读4次

    主要两个要点:

    • 实现指定时间执行任务
    • 实现按照指定周期执行任务

    定时器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方法,参考的则是上一任务的“结束”时间。

    相关文章

      网友评论

          本文标题:Timer定时器

          本文链接:https://www.haomeiwen.com/subject/pzfujftx.html