当前位置: 代码迷 >> 综合 >> 【多线程】Timer 和 ScheduledThreadPoolExecutor
  详细解决方案

【多线程】Timer 和 ScheduledThreadPoolExecutor

热度:32   发布时间:2023-09-20 23:49:46.0

一、周期性任务实现

1.1 应用

在实际应用中,我们需要创建一些延迟性的、周期性的任务,如每隔一小时记录一次日志、每隔一小时统计一次数据等。在 java 中给我们提供了两个实现方式,分别为 Timer 和 ScheduledThreadPoolExecutor。

 

1.2 对比

1.2.1 两者对比

  Timer ScheduledThreadPoolExecutor
线程 只支持单线程 支持多线程
多任务 任务之间互相影响 任务直接隔离
调度时间 绝对时间(受系统时间影响) 相对时间
异常 单任务异常,则后续任务受影响 无影响
支持版本  > JDK1.3  > JDK1.5
推荐度 不推荐 推荐使用

 

1.2.2 Timer 存在的问题

● Timer的问题:依赖系统时间,系统时间变化影响精度

Timer 类的调度是基于系统时间的,而不是相对时间,因为 Timer 类对系统时钟的变化是敏感的。例如,设定了一个每隔 10 秒执行一次的任务,在某个时刻,系统时间提前了5秒,则下一个任务就会在5秒后执行,而不是10秒后从而影响到后续的所有任务执行

● ScheduledThreadPoolExecutor 如何解决

ScheduledThreadPoolExecutor 中,任务调度是基于相对时间的。它在任务的内部存储了该任务距离下次调度还需要的时间(使用的是基于 System#nanoTime实现的相对时间 ,不会因为系统时间改变而改变,如距离下次执行还有10秒,不会因为将系统时间调前6秒而变成4秒后执行)

 

二、实现方式

2.1 Timer 实现

public class TestTimer {public static void main(String[] args) {String time = new SimpleDateFormat("HH:mm:ss").format(new Date());System.out.println("Start time : " + time);Timer timer = new Timer();TimerTask task = new TimerTask() {@Overridepublic void run() {// TODO Auto-generated method stubString time = new SimpleDateFormat("HH:mm:ss").format(new Date());System.out.println("Now Time : " + time);}};// 定义方法在多少秒后第一次被执行int delay = 1000; // 定义方法每次调用的间隔时间int period = 5000;timer.schedule(task, delay, period);}
}

2.2 ScheduledThreadPoolExecutor 实现

public class TestScheduledThreadPoolExecutor {public static void main(String[] args) {String time = new SimpleDateFormat("HH:mm:ss").format(new Date());System.out.println("Start time : " + time);ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(5); //创建5个执行线程Runnable runnable = new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubString time = new SimpleDateFormat("HH:mm:ss").format(new Date());System.out.println("Now Time : " + time);}};executor.scheduleWithFixedDelay(runnable, 2, 3, TimeUnit.SECONDS);}
}

 

 

 

 

 

 

  相关解决方案