java定时器Timer详解

版权声明:如果觉得我的博客对你有帮助, 请点赞或评论! https://blog.csdn.net/zongf0504/article/details/88925009

Timer 是jdk 自身提供的定时器, 可使用于实现一些简单的定时任务,如在某一时刻执行一次任务或以固定时间间隔执行任务. 一个Timer 实例可调度多个TimerTask, 底层使用队列(TaskQueue)存储, 不能并发启动定时任务. 因此, 对于复杂的定时任务, 笔者推荐使用quartz.

1. Timer 常用API

默认情况下,Timer 创建的线程为用户线程, 如果想让其为守护进程的话, 创建时需要设置isDaemon 为true.

方法签名 方法描述
public Timer(String name) 构造方法, 创建定时器, 并指定线程名称. 以定时调度线程为用户线程
public Timer(boolean isDaemon) 构造方法, 创建定时器, isDaemon 设置为trues时表示以守护线程执行
public Timer(String name, boolean isDaemon)
public void schedule(TimerTask task, long delay) 只调度一次, 延迟delay毫秒之后执行
public void schedule(TimerTask task, Date time) 只调度一次, 在具体时刻time 执行
public void schedule(TimerTask task, long delay, long period) 循环调度, 在delay毫秒之后开始,每隔period毫秒执行一次
public void schedule(TimerTask task, Date firstTime, long period) 循环调度, 在时刻firstTime开始调度, 每隔period毫秒执行一次
public void scheduleAtFixedRate(TimerTask task, long delay, long period) 和schedule方法类似, 只是错过的任务会被继续执行
public void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) 和schedule方法类似, 只是错过的任务会被继续执行
public int purge() 清理所有已取消状态的TimerTask
public void cancel() 取消所有调度

2. 调度测试

2.1 延时调度一次

程序启动3秒之后, 执行一次

public static void main(String[] args) throws InterruptedException {
    // 创建定时器
    Timer timer = new Timer("myTimer");

    // 创建定时任务
    TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            System.out.println(LocalDateTime.now() + "-hello");
        }
    };

    // 添加调度
    timer.schedule(timerTask ,3000);
}

2.2 定时调度一次

定时任务在下一分钟00秒时执行一次

public static void main(String[] args) throws InterruptedException {

    // 创建定时器
    Timer timer = new Timer("myTimer");

    // 创建定时任务
    TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            System.out.println(LocalDateTime.now() + "-hello");
        }
    };

    Date nextMinute = nextMinute();
    System.out.println("now:" + new Date() + ", execute:" + nextMinute);

    // 添加调度
    timer.schedule(timerTask ,nextMinute);

}

// 获取下一分钟的时间
private static Date nextMinute(){

    Calendar calendar = Calendar.getInstance();

    calendar.add(Calendar.MINUTE, 1);

    calendar.add(Calendar.SECOND, -calendar.get(Calendar.SECOND));

    return calendar.getTime();

}

2.3 循环调度n次

定时任务每隔1秒中执行一次, 执行n次后停止

public static void main(String[] args) throws InterruptedException {

     // 创建定时器
     Timer timer = new Timer("myTimer");

     // 创建定时任务
     TimerTask timerTask = new TimerTask() {

         private int times = 0;
         @Override
         public void run() {
             // 执行5次后, 取消任务
             if(++times ==5 ){
                 this.cancel();
             }

             System.out.println(LocalDateTime.now() + "-hello, times:" + times);
         }
     };

     // 添加调度
     timer.schedule(timerTask ,0, 1000l);
}

2.4 无限循环调度

定时任务每隔1秒中执行一次, 无限循环

public static void main(String[] args) throws InterruptedException {

    // 创建定时器
    Timer timer = new Timer("myTimer");

    // 创建定时任务
    TimerTask timerTask = new TimerTask() {

        @Override
        public void run() {

            System.out.println(LocalDateTime.now() + "-hello");
        }
    };

    // 添加调度
    timer.schedule(timerTask ,0, 1000l);

}

3. scheduleAtFixedRate 与 schedule 区别

scheduleAtFixedRate和schedule 的唯一区别就是, schedule 会将错过执行的定时任务丢弃, 而scheduleAtFixedRate 则会补上。

3.1 测试用例

public static void main(String[] args) {

        TimerTask timerTask = new TimerTask() {

            private int times = 0;
            @Override
            public void run() {

                try {

                    if(times++ ==3){
                        this.cancel();
                    }

                    System.out.printf("planExecTime:%s, now:%s, times:%s\n", new Date(scheduledExecutionTime()), new Date(), times);
                    Thread.sleep(3000);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        };

        Timer timer = new Timer("myTimer");
        timer.schedule(timerTask, nextMinute(), 1000);
    }

    private static Date nextMinute(){

        Calendar calendar = Calendar.getInstance();

        calendar.add(Calendar.MINUTE, 1);

        calendar.add(Calendar.SECOND, -calendar.get(Calendar.SECOND));

        return calendar.getTime();

    }

3.2 scheduleAtFixedRate 调度结果

从输出结果上来看, 定时任务计划执行时间与实际执行时间只有第一次一致,其它都不一致。 在定时任务执行的时间内,本应该执行的定时任务会依次被执行。

planExecTime:Sun Mar 31 18:03:00 CST 2019, now:Sun Mar 31 18:03:00 CST 2019, times:1
planExecTime:Sun Mar 31 18:03:01 CST 2019, now:Sun Mar 31 18:03:03 CST 2019, times:2
planExecTime:Sun Mar 31 18:03:02 CST 2019, now:Sun Mar 31 18:03:06 CST 2019, times:3
planExecTime:Sun Mar 31 18:03:03 CST 2019, now:Sun Mar 31 18:03:09 CST 2019, times:4

3.2 schedule 调度结果

从输出结果上可以看出, 计划执行时间和实际执行时间一致. 虽然笔者的调度时间为每隔1秒, 但是定时任务执行需要3秒的时间。 在定时任务执行期间,本应该有的调度全部丢弃。

planExecTime:Sun Mar 31 18:01:00 CST 2019, now:Sun Mar 31 18:01:00 CST 2019, times:1
planExecTime:Sun Mar 31 18:01:03 CST 2019, now:Sun Mar 31 18:01:03 CST 2019, times:2
planExecTime:Sun Mar 31 18:01:06 CST 2019, now:Sun Mar 31 18:01:06 CST 2019, times:3
planExecTime:Sun Mar 31 18:01:09 CST 2019, now:Sun Mar 31 18:01:09 CST 2019, times:4

猜你喜欢

转载自blog.csdn.net/zongf0504/article/details/88925009