java在jdk1.3中推出了定时器类Timer,而后在jdk1.5后由Dou Lea从新开发出了支持多线程的ScheduleThreadPoolExecutor,从后者的表现来看,可以考虑完全替代Timer了。
Timer与ScheduleThreadPoolExecutor对比:
1.
Timer始于jdk1.3,其原理是利用一个TimerTask数组当作队列,将所有定时任务添加到此队列里面去。 然后启动一个线程,当队列为空时,此线程会阻塞,当队列里面有数据时,线程会去除一个TimerTask来判断
是否到时间需要运行此任务,如果运行时间小于或等于当前时间时则开始运行任务。 由于其单线程的本质,所以会带来几个问题(详细代码在后面):
第一,当我们添加到定时器中的任务比较耗时时,由于此定时器是单线程顺序执行定时器任务,所以会影响后续任务的按时执行。
//问题一示例: m_timer.scheduleAtFixedRate(new TaskUseLongTime(), 1000, 5000); m_timer.scheduleAtFixedRate(new TaskNormal(), 5000, 3000); 运行结果: 14:44:29: timer is sleeping 10 seconds 14:44:39: Task Normal executed 14:44:39: timer is sleeping 10 seconds 14:44:49: Task Normal executed 14:44:49: Task Normal executed 14:44:49: timer is sleeping 10 seconds 结果分析:TaskNormal任务无法保证3秒运行一次,其只能等待TaskUseLongTime运行结束后才可以。
第二,Timer中的线程仅仅会捕获InterruptedException异常,所以如果我们自定义的定时任务里面没有捕获可能出现的异常而导致异常抛出后,
//问题二示例: m_timer.schedule(new TaskThrowException(), 1000); m_timer.schedule(new TaskNormal(), 2000); 运行结果: 14:47:37: Throw exception Exception in thread "Timer-0" java.lang.RuntimeException at timer_test.TimerTest$TaskThrowException.run(TimerTest.java:85) at java.util.TimerThread.mainLoop(Timer.java:512) at java.util.TimerThread.run(Timer.java:462) 结果分析: 当前一个任务抛出异常后,后面的TaskNormal任务无法继续运行
会导致我们的Timer线程停止,从而另后续的任务无法执行。
第三,其无法处理多个同时发生的定时任务
//问题三示例: m_timer.scheduleAtFixedRate(new TaskUseLongTime("timer1"), 1000, 15000); m_timer.scheduleAtFixedRate(new TaskUseLongTime("timer2"), 1000, 15000); 运行结果: 14:50:16: timer1 is sleeping 10 seconds 14:50:26: timer2 is sleeping 10 seconds 14:50:36: timer2 is sleeping 10 seconds 结果分析: 我的启动时间均是1秒以后,但是timer1和timer2启动的时间明显不一致
代码示例:
/** * @filename TimerTest.java * @date 2014-11-18 */ package timer_test; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class TimerTest { private final Timer m_timer = new Timer(); public static void main(String[] args) { new TimerTest().test(); } public void test() { //问题一示例: m_timer.scheduleAtFixedRate(new TaskUseLongTime(), 1000, 5000); m_timer.scheduleAtFixedRate(new TaskNormal(), 5000, 3000); //问题二示例: // m_timer.schedule(new TaskThrowException(), 1000); // m_timer.schedule(new TaskNormal(), 2000); //问题三示例: // m_timer.scheduleAtFixedRate(new TaskUseLongTime("timer1"), 1000, 5000); // m_timer.scheduleAtFixedRate(new TaskUseLongTime("timer2"), 1000, 5000); } private class TaskUseLongTime extends TimerTask { private String m_taskName = "timer"; public TaskUseLongTime(){} public TaskUseLongTime(String taskName) { m_taskName = taskName; } @Override public void run() { try { System.out.println(getCurrentTime()+": "+m_taskName+" is sleeping 10 seconds"); Thread.sleep(10000); } catch (InterruptedException e) { } } } private class TaskNormal extends TimerTask { @Override public void run() { System.out.println(getCurrentTime()+": Task Normal executed"); } } private class TaskThrowException extends TimerTask { @Override public void run() { System.out.println(getCurrentTime()+": Throw exception"); throw new RuntimeException(); } } private String getCurrentTime() { return new SimpleDateFormat("HH:mm:ss").format(new Date()); } }
2.ScheduleThreadPoolExecutor
ScheduleThreadPoolExecutor始于jdk1.5,是由Dou Lea先生编写的,其利用ThreadPoolExecutor和DelayQueue巧妙的结合完成了多线程定时器的实现,解决了Timer中由于单线程而导致的上述三个缺陷。
问题一中的问题是因为单线程顺序执行导致后续任务无法按时完成,我们看到多线程可以很容易的解决此问题,同时我们注意到TaskUseLongTime的执行时间为10s(请看后续代码),我们定时任务间隔是5秒,但是从结果中发现我们的任务执行间隔却是10秒,所以我们可以判断ScheduleThreadPoolExecutor是采用每线程每任务的模式工作的。
//问题一: m_timer.scheduleAtFixedRate(new TaskUseLongTime(), 1000, 5000, TimeUnit.MILLISECONDS); m_timer.scheduleAtFixedRate(new TaskNormal(), 1000, 5000, TimeUnit.MILLISECONDS); 运行结果: 14:54:37: Task Normal executed 14:54:37: timer is sleeping 10 seconds 14:54:42: Task Normal executed 14:54:47: Task Normal executed 14:54:47: timer is sleeping 10 seconds 14:54:52: Task Normal executed
问题二中我们发现当抛出异常的任务执行后不影响其他任务的运行,同时我们发现在运行结果里面没有将我们的异常抛出,这是因为ScheduleThreadPoolExecutor类在执行完定时任务后会返回一个ScheduledFuture运行结果,不论结果是顺利完成还是有异常均会保存在这里。
//问题二: m_timer.scheduleAtFixedRate(new TaskThrowException(), 1000, 5000, TimeUnit.MILLISECONDS); m_timer.scheduleAtFixedRate(new TaskNormal(), 1000, 5000, TimeUnit.MILLISECONDS); 运行结果: 14:58:36: Throw exception 14:58:36: Task Normal executed 14:58:41: Task Normal executed 14:58:46: Task Normal executed 14:58:51: Task Normal executed 14:58:56: Task Normal executed
问题三由于是多线程所以我们可以保证我们的定时任务可以同时执行
//问题三: m_timer.scheduleAtFixedRate(new TaskUseLongTime("timer1"), 1000, 5000, TimeUnit.MILLISECONDS); m_timer.scheduleAtFixedRate(new TaskUseLongTime("timer2"), 1000, 5000, TimeUnit.MILLISECONDS); 运行结果: 15:01:12: timer1 is sleeping 10 seconds 15:01:12: timer2 is sleeping 10 seconds 15:01:22: timer2 is sleeping 10 seconds 15:01:22: timer1 is sleeping 10 seconds 15:01:32: timer1 is sleeping 10 seconds 15:01:32: timer2 is sleeping 10 seconds
详细代码:
/** * @filename ScheduleThreadPoolExecutorTest.java * @date 2014-11-18 */ package timer_test; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.Callable; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class ScheduleThreadPoolExecutorTest { private final ScheduledThreadPoolExecutor m_timer = new ScheduledThreadPoolExecutor(10); public static void main(String[] args) { ScheduleThreadPoolExecutorTest timerTest = new ScheduleThreadPoolExecutorTest(); timerTest.test(); try { Thread.sleep(100000); } catch (InterruptedException e) { }finally { timerTest.shutdown(); } } public void shutdown() { m_timer.shutdown(); } public void test() { //问题一: // m_timer.scheduleAtFixedRate(new TaskUseLongTime(), 1000, 5000, TimeUnit.MILLISECONDS); // m_timer.scheduleAtFixedRate(new TaskNormal(), 1000, 5000, TimeUnit.MILLISECONDS); //问题二: // m_timer.scheduleAtFixedRate(new TaskThrowException(), 1000, 5000, TimeUnit.MILLISECONDS); // m_timer.scheduleAtFixedRate(new TaskNormal(), 1000, 5000, TimeUnit.MILLISECONDS); //问题三: m_timer.scheduleAtFixedRate(new TaskUseLongTime("timer1"), 1000, 5000, TimeUnit.MILLISECONDS); m_timer.scheduleAtFixedRate(new TaskUseLongTime("timer2"), 1000, 5000, TimeUnit.MILLISECONDS); } private class TaskUseLongTime implements Callable<Integer>, Runnable { private String m_taskName = "timer"; private TaskUseLongTime(){} private TaskUseLongTime(String taskName) { m_taskName = taskName; } public void run() { try { System.out.println(getCurrentTime()+": "+m_taskName+" is sleeping 10 seconds"); Thread.sleep(10000); } catch (InterruptedException e) { } } public Integer call() throws Exception { run(); return 0; } } @SuppressWarnings("unused") private class TaskNormal implements Callable<Integer>, Runnable { public Integer call() throws Exception { run(); return 0; } public void run() { System.out.println(getCurrentTime()+": Task Normal executed"); } } @SuppressWarnings("unused") private class TaskThrowException implements Callable<Integer>, Runnable { public Integer call() throws Exception { System.out.println(getCurrentTime()+": Throw exception"); throw new RuntimeException(); } public void run() { System.out.println(getCurrentTime()+": Throw exception"); throw new RuntimeException(); } } private String getCurrentTime() { return new SimpleDateFormat("HH:mm:ss").format(new Date()); } }
相关推荐
浅谈java定时器的发展历程 Java 定时器是 Java 语言中的一种机制,用于在特定的时间或周期执行某些操作。Java 定时器的发展历程可以追溯到 JDK 1.3,自此以来,它经历了多次更新和改进。下面我们将从 Java 定时器的...
Java定时器(java.util.Timer)是Java标准库中用于调度任务执行的重要工具,它允许我们按照预设的时间间隔执行特定的任务。在Java程序设计中,定时器常常用于实现周期性的任务,比如定时备份数据、定时检查系统状态...
JAVA定时器 JAVA定时器是一种基于Quartz框架的任务调度器,用于在指定的时间执行特定的任务。在 Spring 框架中,JAVA定时器可以与Quartz框架集成,实现自动执行任务的功能。 1. JAVA定时器的基本概念 JAVA定时器...
Java定时器是Java编程语言中用于执行特定任务的调度工具,它允许程序员在指定的时间间隔后执行特定的代码块或任务。在Java中,我们主要使用`java.util.Timer`类和`java.util.TimerTask`类来实现定时器功能。这两个类...
java定时器,import java.util.Calendar; import java.util.Date; import java.util.Timer; import java.util.TimerTask; 规定每天几点执行一次
Java定时器(Timer)是Java Swing库中的一个类,它提供了调度任务在未来某个时间执行的能力。这个类主要用于在GUI应用程序中实现定时触发某些操作,比如更新界面、执行动画或者执行周期性的后台任务。Timer类结合了...
Java定时器和Spring定时器是Java开发中用于执行周期性任务的重要工具,它们在系统维护、数据同步、报告生成等场景中发挥着关键作用。本文将深入探讨这两个概念,以及如何在Spring框架中配置和使用定时器。 首先,...
JAVA定时器,只要服务开启,就能指定某些代码在某个时刻执行,例如:监狱里罪犯的余刑天数,每天都要减少,就可以设置一个定时器在每天的23:59:59来执行减少余刑天数的天。
Java定时器框架Quartz是Java开发中用于任务调度的一个强大工具,它允许开发者精确地控制任务的执行时间,包括一次性任务和周期性任务。Quartz以其灵活性和稳定性,在企业级应用中广泛使用,尤其在需要定期执行后台...
在应用开发中,经常需要一些周期性的操作,比如每5分钟执行某一操作等。 对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。
Java定时器服务是Java平台中用于执行定时任务的关键组件,它允许开发者安排未来或定期的任务执行。在Java中,我们通常使用`java.util.Timer`类和`java.util.TimerTask`类来实现定时服务。这两个类提供了创建、调度和...
### Java定时器实现详解 在Java编程中,定时任务是常见的需求之一,无论是服务器的定期维护、数据同步,还是客户端的动画更新等场景,都需要用到定时器来精确控制任务的执行时间。本文将深入解析一个基于Java的简单...
Java定时器(Timer)是Java语言中用于调度任务的一个重要工具,它可以帮助我们在特定时间执行一次或重复执行某个任务。这个“java定时器.rar”压缩包可能包含了关于如何使用Java定时器的相关示例代码和教程。 Java...
Java Web定时器主要指的是在Java Web应用程序中实现定时任务的功能,这在许多业务场景中都是必要的,例如数据备份、报表生成、邮件发送等。在Java中,我们可以利用内置的`java.util.Timer`类或者Spring框架的`@...
java定时器例子,使用 java.util.TimerTask 类来实现定时执行
在Java编程中,定时器(Timer)是一种非常实用的工具,可以用来安排任务在未来的某个时间点执行或者定期执行。这个“Java创建定时器.rar”压缩包中的代码示例,显然是一个展示了如何在Java中利用定时器实现特定功能...
Java定时器和时间处理是Java开发中的重要组成部分,特别是在需要执行周期性任务或者对时间有精确控制的应用场景中。本文将深入探讨Java定时器(Timer)的使用以及如何获取和处理年月日、时间节点等时间相关的信息。 ...
JAVA中定时器的使用 JAVA 中的定时器是指在特定的时间或时间间隔执行某个任务的机制。JAVA 中提供了多种方式来实现定时器,包括使用 Timer 和 TimerTask 类,使用 ScheduledExecutorService 等。 在 JAVA 中,...