0
点赞
收藏
分享

微信扫一扫

java定时工具的辟谣

定时器Timer


Timer的常用方法
  • Timer timer = new Timer()
  • 构建TimerTask实例
TimerTask task = new TimerTask() {   
    public void run() {   
        ... //每次需要执行的业务代码
        cancel();//可以让该task退出调度
    }   
};
  • cancel取消全部定时任务
  • schedule调度定时任务

timer.schedule(task, time)

timer.schedule(task, delay)

timer.schedule(task, firstTime, period)

timer.schedule(task, delay, period)

tips

验证代码:

Timer timer = new Timer();
//耗时2s左右的任务
TimerTask task1 = new TimerTask() {
    @Override
    public void run() {
        //获得该任务该次执行的期望开始时间
        System.out.println("expect start time: " + new Date(scheduledExecutionTime()));
        System.out.println("task1 start: " + new Date());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {}
        System.out.println("task1 end: " + new Date());
    }
};
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, -11);
Date date = calendar.getTime();
System.out.println("now: " + new Date());
System.out.println("timer start: " + date);
//设置调度的启动时间为11s前
timer.schedule(task1, date, 5000);

结果:

//当前时间16:05:51,设置的启动时间为16:05:40
now: Mon Nov 20 16:05:51 CST 2017
timer start: Mon Nov 20 16:05:40 CST 2017
//立即执行,并将期望的执行时间设为当前时间
expect start time: Mon Nov 20 16:05:51 CST 2017
task1 start: Mon Nov 20 16:05:51 CST 2017
task1 end: Mon Nov 20 16:05:53 CST 2017
//以实际的启动时间16:05:51为基准,间隔5秒周期执行,而不按照设置的16:05:40为基准
//下一次任务的开始时间以上次任务的开始时间为准,间隔5秒再次执行
expect start time: Mon Nov 20 16:05:56 CST 2017
task1 start: Mon Nov 20 16:05:56 CST 2017
task1 end: Mon Nov 20 16:05:58 CST 2017
  • scheduleAtFixedRate调度定时任务

timer.scheduleAtFixedRate(task, delay, period)

timer.scheduleAtFixedRate(task, firstTime, period)

tips

验证代码:

Timer timer = new Timer();
//耗时2s左右的任务
TimerTask task1 = new TimerTask() {
    @Override
    public void run() {
        //获得该任务该次执行的期望开始时间
        System.out.println("expect run time: " + new Date(scheduledExecutionTime()));
        System.out.println("task1 start: " + new Date());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("task1 end: " + new Date());
    }
};
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.SECOND, -11);
Date date = calendar.getTime();
System.out.println("now: " + new Date());
System.out.println("timer start: " + date);
//设置调度的启动时间为11s前
timer.scheduleAtFixedRate(task1, date, 5000);

结果:

//当前时间15:38:06,设置的启动时间为15:37:55
now: Mon Nov 20 15:38:06 CST 2017
timer start: Mon Nov 20 15:37:55 CST 2017
//期望开始时间小于实际开始时间,追赶进度
expect run time: Mon Nov 20 15:37:55 CST 2017
task1 start: Mon Nov 20 15:38:06 CST 2017
task1 end: Mon Nov 20 15:38:08 CST 2017
//期望开始时间小于实际开始时间,追赶进度
expect run time: Mon Nov 20 15:38:00 CST 2017
task1 start: Mon Nov 20 15:38:08 CST 2017
task1 end: Mon Nov 20 15:38:10 CST 2017
//期望开始时间小于实际开始时间,追赶进度
expect run time: Mon Nov 20 15:38:05 CST 2017
task1 start: Mon Nov 20 15:38:10 CST 2017
task1 end: Mon Nov 20 15:38:12 CST 2017
//期望开始时间小于实际开始时间,追赶进度
expect run time: Mon Nov 20 15:38:10 CST 2017
task1 start: Mon Nov 20 15:38:12 CST 2017
task1 end: Mon Nov 20 15:38:14 CST 2017
//进度追上了,以设置的启动时间15:37:55为基准
//没有按照上次任务的开始时间15:38:12间隔5秒执行
expect run time: Mon Nov 20 15:38:15 CST 2017
task1 start: Mon Nov 20 15:38:15 CST 2017
task1 end: Mon Nov 20 15:38:17 CST 2017
//从此开始正常执行
expect run time: Mon Nov 20 15:38:20 CST 2017
task1 start: Mon Nov 20 15:38:20 CST 2017
task1 end: Mon Nov 20 15:38:22 CST 2017
schedule和scheduleAtFixedRate总结

ScheduledThreadPoolExecutor


ScheduledThreadPoolExecutor的常用方法

ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)

<V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)

ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long period, TimeUnit unit)

ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)

future模式可以看这里

验证代码:

TimerTask task1 = new TimerTask() {
    @Override
    public void run() {
        //获得该任务该次执行的期望开始时间
        System.out.println("expect start time: " + new Date(scheduledExecutionTime()));
        System.out.println("task1 start: " + new Date());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("task1 end: " + new Date());
    }
};
TimerTask task2 = new TimerTask() {
    @Override
    public void run() {
        //获得该任务该次执行的期望开始时间
        System.out.println("expect start time: " + new Date(scheduledExecutionTime()));
        System.out.println("task2 start: " + new Date());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
        }
        System.out.println("task2 end: " + new Date());
    }
};
System.out.println("now: " + new Date());
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
executor.scheduleWithFixedDelay(task1, 0, 1000, TimeUnit.MILLISECONDS);
executor.scheduleAtFixedRate(task2, 0, 1000, TimeUnit.MILLISECONDS);

结果:

//可以看到ScheduledThreadPoolExecutor不会设置TimerTask的期望开始时间
//为了便于阅读,下面的这条日志删掉了
expect start time: Thu Jan 01 08:00:00 CST 1970
expect start time: Thu Jan 01 08:00:00 CST 1970
//两个任务分别占用一个线程,因此同时启动
task1 start: Mon Nov 20 19:58:24 CST 2017
task2 start: Mon Nov 20 19:58:24 CST 2017
//每个任务都耗时2s,虽然设定的period是1ms,但是任务执行期间并没有再次启动
task2 end: Mon Nov 20 19:58:26 CST 2017
task1 end: Mon Nov 20 19:58:26 CST 2017
//task2按照上次任务的开始时间+1s执行,因为实行时间(2s)大于1s,所以每次都会立即执行
task2 start: Mon Nov 20 19:58:26 CST 2017
//task1按照上次任务的结束时间(19:58:26)+1s执行,所以是19:58:27开始执行
task1 start: Mon Nov 20 19:58:27 CST 2017
task2 end: Mon Nov 20 19:58:28 CST 2017
task2 start: Mon Nov 20 19:58:28 CST 2017
task1 end: Mon Nov 20 19:58:29 CST 2017
task2 end: Mon Nov 20 19:58:30 CST 2017
ScheduledThreadPoolExecutor优点

举报

相关推荐

0 条评论