美文网首页
JavaEE进阶知识学习-----定时任务调度Timer-入门简

JavaEE进阶知识学习-----定时任务调度Timer-入门简

作者: Waldeinsamkeit4 | 来源:发表于2018-02-25 13:21 被阅读0次

    什么是定时任务调度

    基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行的任务。

    Timer定义

    Time是jdk自带的一个类,位于java.lang.Object下的java.util.Timer,定义为,有且仅有一个后台线程对多个业务线程进行定时频率的调度。

    Timer的主要构件

    Timer和TimerTask,timer定时调用TimerTask。

    Timer的Hello world

    业务逻辑的MyTimerTask类

    public class MyTimerTask extends TimerTask{
        private String name;
        public MyTimerTask(String inputName) {
            this.name = inputName;
        }
        @Override
        public void run() {
            //打印当前name的值
            System.out.println("当前的name值为:"+name);
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    

    Timer测试类的编写

    public class MyTimer {
        public static void main(String[] args) {
            //创建一个timer实例
            Timer timer = new Timer();
            //创建一个MyTimerTask实例
            MyTimerTask myTimerTask = new MyTimerTask("张三丰");
            //设置timer定时定频率的调用myTimerTask的业务逻辑
            //第一次执行是在两秒之后,之后每隔一秒执行一次
            timer.schedule(myTimerTask, 2000L,1000L);
        }
    }
    

    Timer的定时调度函数的用法

    schedule的四种用法

    1.timer.schedule(task, time);在时间等于或超过timer的时候执行且仅执行一次task。

    • task:所有安排的任务
    • time:执行任务的时间

    实例如下:
    MyTimerTask类做了如下的修改

    public class MyTimerTask extends TimerTask{
        private String name;
        public MyTimerTask(String inputName) {
            this.name = inputName;
        }
        @Override
        public void run() {
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间为:"+sf.format(calendar.getTime()));
            //打印当前name的值
            System.out.println("当前的name值为:"+name);
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    

    MyTimer类详情如下

    public class MyTimer {
        public static void main(String[] args) {
            //创建一个timer实例
            Timer timer = new Timer();
            //创建一个MyTimerTask实例
            MyTimerTask myTimerTask = new MyTimerTask("张三丰");
            //设置timer定时定频率的调用myTimerTask的业务逻辑
            //获取当前时间,并设置成为距离当前时间的后三秒的时间
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间为:"+sf.format(calendar.getTime()));
            calendar.add(Calendar.SECOND, 3);
            myTimerTask.setName("schedule的第一种用法:");
            timer.schedule(myTimerTask, calendar.getTime());
        }
    }
    

    结果,在当前时间后三秒只打印一次name的值。

    2.timer.schedule(task, delay);等待delay毫秒后执行且执行一次task.

    timer.schedule(myTimerTask, 1000);
    

    3.timer.schedule(task, firstTime, period);时间等于或者超过timer时首次执行task,之后每隔period毫秒重复执行一次task。

    • task:所有安排的任务
    • firstTime:首次执行任务的时间
    • period:执行一次task的时间间隔,单位是毫秒。

    实例如下:在第一种用法上修改为如下,表示当前时间三秒后第一次打印,之后每隔两秒打印一次。

    timer.schedule(myTimerTask, calendar.getTime(),2000);
    

    4.timer.schedule(task, delay, period);等待delay毫秒之后首次执行一次task,之后每隔period秒后重复执行一次task。

    timer.schedule(myTimerTask, 3000,1000);
    

    scheduleAtFixedRate的两种用法

    1.timer.scheduleAtFixedRate(task, firstTime, period);时间等于或超过firsttime时首次执行task,之后每隔period毫秒重复执行一次task。

    timer.scheduleAtFixedRate(myTimerTask, calendar.getTime(), 1000);
    

    2.timer.scheduleAtFixedRate(task, delay, period);等待delay毫秒后首次执行task,之后每隔period毫秒重复执行一次task。

    timer.scheduleAtFixedRate(myTimerTask, 3000, 1000);
    

    其他重要函数

    TimerTask的cancel()scheduledExecutionTime()

    cancel()取消当前TimerTask的任务。

    实例:任务延迟三秒执行,之后每隔一秒执行一次,执行三次后结束,需要修改MyTimerTask

    public class MyTimerTask extends TimerTask{
        private String name;
        private Integer count = 0;
        public MyTimerTask(String inputName) {
            this.name = inputName;
        }
        @Override
        public void run() {
            if(count < 3){
                Calendar calendar = Calendar.getInstance();
                SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                System.out.println("当前时间为:"+sf.format(calendar.getTime()));
                //打印当前name的值
                System.out.println("当前的name值为:"+name);
                count++;
            }else{
                cancel();//取消任务
                System.out.println("任务被取消了");
            }
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    

    scheduledExecutionTime()返回此任务最近实际执行的已安排执行的时间,返回值为long型

    timer.schedule(myTimerTask, 3000);
    System.out.println("任务将要执行的时间为:"+sf.format(myTimerTask.scheduledExecutionTime()));
    

    其实就是,我们如果要延迟三秒执行,那么打印的就是执行时间。
    注意:增加了执行次数统计器。以此来判断执行的次数。

    timer的cancel()和purge();

    cancel();终止计时器,丢弃所有当前已安排的任务

    public class MyTimer2 {
        public static void main(String[] args) throws InterruptedException {
            //创建timer实例
            Timer timer = new Timer();
            //创建TimerTask实例
            MyTimerTask task1 = new MyTimerTask("任务1");
            MyTimerTask task2 = new MyTimerTask("任务2");
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间为:"+sf.format(calendar.getTime()));
            //task1是首次执行距离现在时间3秒,之后每隔2秒执行一次。
            //task2是首次执行距离现在时间1秒,之后每隔2秒执行一次。
            timer.schedule(task1, 3000,2000);
            timer.schedule(task2, 1000,2000);
            //休眠5秒
            Thread.sleep(5000);
            Date date = new Date();
            System.out.println("现在时间是:"+sf.format(date));
            //取消所有任务
            timer.cancel();
            System.out.println("所有任务被取消");
            
        }
    }
    

    purge();从此计时器的任务队列中移除所有已取消的任务,返回移除的任务数。

    public class MyTimer2 {
        public static void main(String[] args) throws InterruptedException {
            //创建timer实例
            Timer timer = new Timer();
            //创建TimerTask实例
            MyTimerTask task1 = new MyTimerTask("任务1");
            MyTimerTask task2 = new MyTimerTask("任务2");
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间为:"+sf.format(calendar.getTime()));
            //task1是首次执行距离现在时间3秒,之后每隔2秒执行一次。
            //task2是首次执行距离现在时间1秒,之后每隔2秒执行一次。
            timer.schedule(task1, 3000,2000);
            timer.schedule(task2, 3000,2000);
            System.out.println("当前已取消的任务数:"+timer.purge());
            //休眠5秒
            Thread.sleep(5000);
            Date date = new Date();
            System.out.println("现在时间是:"+sf.format(date));
            //取消所有任务
            task2.cancel();
            System.out.println("当前已取消的任务数:"+timer.purge());
            
        }
    }
    

    schedule与scheduleAtFixedRate的区别

    1.当首次执行的时间早于当前时间的时候
    在schedule中如果首次执行的时间早于当前时间,那么第一次执行的时间还是会以当前时间为准。

    public class MyTimer {
        public static void main(String[] args) {
            Calendar calendar = Calendar.getInstance();
            final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间为:"+sf.format(calendar.getTime()));
            //设置时间为6秒前
            calendar.add(Calendar.SECOND, -6);
            Timer timer = new Timer();
            timer.schedule(new TimerTask() {
                
                @Override
                public void run() {
                    //打印当前计划执行的时间
                    System.out.println("计划要执行的时间:"+sf.format(scheduledExecutionTime()));
                    System.out.println("任务正在执行");
                }
            }, calendar.getTime(),2000);
            
        }
    
    }
    

    2.任务执行的时间超出任务的执行周期时间的时候
    scheduleAtFixedRate在这种情况下会从首次执行时间开始立马执行,这里就涉及到了同步的问题。

    public class MyTimer {
        public static void main(String[] args) {
            Calendar calendar = Calendar.getInstance();
            final SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间为:"+sf.format(calendar.getTime()));
            //设置时间为6秒前
            calendar.add(Calendar.SECOND, -6);
            Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask() {
                
                @Override
                public void run() {
                    //打印当前计划执行的时间
                    System.out.println("计划要执行的时间:"+sf.format(scheduledExecutionTime()));
                    System.out.println("任务正在执行");
                }
            }, calendar.getTime(),2000);
            
        }
    
    }
    

    实例

    有两个定时机器人,一个负责灌水,一个负责跳舞,当桶被灌满后,停止四秒,跳舞也结束运行。

    跳舞机器人

    public class DancingRobot extends TimerTask{
    
        @Override
        public void run() {
            //获取最近的一次任务执行时间,并将其格式化
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("下一次任务执行的时间为:"+sf.format(scheduledExecutionTime()));
            System.out.println("跳舞机器人正在欢快的跳舞...");
            
        }
    
    }
    

    灌水机器人

    public class WaterRobot extends TimerTask{
        private Timer timer;
        //桶的最大容量为5L
        private Integer bucketCappacity = 0;
        public WaterRobot(Timer timer) {
            this.timer = timer;
        }
        @Override
        public void run() {
            if(bucketCappacity < 5){
                System.out.println("灌水机器人努力灌水中...");
                bucketCappacity++;
            }else{
                //水满之后就停止执行
                cancel();
                System.out.println("time中取消的任务数:"+timer.purge());
                //等待两秒后,终止timer里面的所有内容
                System.out.println("水已经灌满了...");
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                timer.cancel();
                System.out.println("所有的任务都取消了");
            }
        }
    
    }
    

    执行程序

    public class Exector {
        public static void main(String[] args) {
            Timer timer = new Timer();
            Calendar calendar = Calendar.getInstance();
            SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.println("当前时间为:"+sf.format(calendar.getTime()));
            
            DancingRobot dr = new DancingRobot();
            WaterRobot wr = new WaterRobot(timer);
            
            timer.schedule(dr, calendar.getTime(),2000);
            timer.scheduleAtFixedRate(wr, calendar.getTime(), 1000);
        }
    
    }
    

    缺陷

    1.不能满足我们的并发需求。
    2.如果一个timertask抛出异常,就会终止Timer中的所有任务。

    相关文章

      网友评论

          本文标题:JavaEE进阶知识学习-----定时任务调度Timer-入门简

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