【多线程】Timer 和 ScheduledThreadPoolExecutor

一、周期性任务实现

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() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                String 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() {
 
			@Override
			public void run() {
				// TODO Auto-generated method stub
				String time = new SimpleDateFormat("HH:mm:ss").format(new Date());
				System.out.println("Now Time : " + time);
			}
		};
		executor.scheduleWithFixedDelay(runnable, 2, 3, TimeUnit.SECONDS);
	}
}

 

 

 

 

 

 

你可能感兴趣的:(Java)