惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

美团技术团队
D
DataBreaches.Net
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
D
Docker
N
Netflix TechBlog - Medium
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
C
Check Point Blog
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
V
Visual Studio Blog
IT之家
IT之家
月光博客
月光博客
U
Unit 42
K
Kaspersky official blog
T
Threatpost
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
GbyAI
GbyAI
P
Proofpoint News Feed
Last Week in AI
Last Week in AI
云风的 BLOG
云风的 BLOG
酷 壳 – CoolShell
酷 壳 – CoolShell
I
InfoQ
Engineering at Meta
Engineering at Meta
Recorded Future
Recorded Future
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
S
Security @ Cisco Blogs
MyScale Blog
MyScale Blog
大猫的无限游戏
大猫的无限游戏
Security Archives - TechRepublic
Security Archives - TechRepublic
Webroot Blog
Webroot Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
Schneier on Security
S
Secure Thoughts
The Register - Security
The Register - Security
B
Blog RSS Feed
The Last Watchdog
The Last Watchdog
P
Palo Alto Networks Blog
爱范儿
爱范儿
B
Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
N
News and Events Feed by Topic
阮一峰的网络日志
阮一峰的网络日志
L
LINUX DO - 热门话题
C
Cisco Blogs
Spread Privacy
Spread Privacy
F
Full Disclosure
博客园 - 聂微东
T
The Blog of Author Tim Ferriss

博客园 - Bryan Wong

Pushlets的初始化陷阱 在Tomcat部署Solr 4.3 Spring Security如何防止会话固定攻击(session fixation attack) Lucene索引,查询及高亮显示 记录几个Json的lib 蛋疼的腾讯微博数据类型和API文档 语言检测工具language-detection 你所不知道的Quartz特性 Spring Data集成MongoDB访问 Jetty的jar包依赖关系图 CAPS & BHCA Java中的集合类图 下载SUSE Linux 10 sp1的经历好曲折 C#代码检查工具:stylecop 圈复杂度基础 Scrum——“鸡”和“猪”的寓言 使用java断言调测程序 无所不能的final关键字 不同于C#的Java值类型和String类型
Jdk自带的定时任务TimerTask和ScheduledExecutorService及其在Spring中的集成
Bryan Wong · 2013-04-14 · via 博客园 - Bryan Wong

1,java.util.Timer和TimerTask是JDK1.3自带的定时任务实现类,使用非常简单,不过由于依赖系统时间,在时间跳变的情况下,执行会出现一些变化。如果时间向后(未来方向)修改,不影响任务执行,但如果向前(过去方向)修改,取决于时间调整的幅度,定时任务可能延迟很久才能回复正常,这在程序运行过程中,可能并不是我们所期望的的,对于一些依赖定时任务执行的关键任务 ,可能导致严重后果。

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		TimerTask task = new TimerTask()
		{
			public void run() 
			{
				System.out.println("Timer task execute " + ++times + " at " + new Date() + 
						",expected executing at " +  new Date(this.scheduledExecutionTime()));
			}
		};
		
		Timer tm = new Timer();
		/**
		 * Timer基于系统时间是准确的前提;执行过程中:
		 * 如果系统时间被往后修改,根据Timer类mainLoop方法中taskFired = (executionTime<=currentTime)的判断,程序还是会继续执行,间隔也不受影响
		 * 如果系统时间被往前修改,仍然是根据上面所述判断,则下一次执行时间会被延后,后面恢复正常
		 */
		tm.schedule(task, new Date(), 2 * 60 * 1000);
	}

2,自打JDK1.5开始,我们可以选择ScheduledExecutorService来替代Timer执行定时任务。ScheduledExecutorService并不是基于绝对的时间和周期,而是基于时间延迟和周期,这样当出现时间跳变(网络延迟/时间服务器同步/人工干预修改时间),定时任务仍然按照原来的时间间隔执行。

public class JdkScheduledExecutorService
{
	private static int times = 0;
	private static long nextExecuteTime = new Date().getTime();

	/**
	 * @param args
	 */
	public static void main(String[] args)
	{
		TimerTask task = new TimerTask()
		{
			public void run() 
			{
				nextExecuteTime += 2 * 60 * 1000;
				System.out.println("Timer task execute " + ++times + " at " + new Date() + 
						",expected executing at " +  new Date(nextExecuteTime));
			}
		};
		
		ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
		service.scheduleAtFixedRate(task, 0, 2, TimeUnit.MINUTES);
	}

}

  上述两段代码可在运行时,分别先后将时间向后修改,观察控制台输出效果,再向前修改并观察效果。

      Spring的Schedule支持多种定时任务实现,具体可参考http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html#threadPoolTaskExecutor

      使用上述Timer时,配置如下(已过时,建议不要再使用)

<context:component-scan base-package="com.bryan.schedule"  use-default-filters="false">
    <context:include-filter type="regex" expression="com.bryan.schedule.SpringTimer.*"/>
 </context:component-scan>
 
 <bean id="testTask" class="org.springframework.scheduling.timer.ScheduledTimerTask">
         <property name="timerTask">
            <ref bean ="timer"/>
         </property>
         <property name="period">
            <value>120000</value>
         </property>
         <property name="delay">
            <value>0</value>
         </property>
    </bean>
 <bean class="org.springframework.scheduling.timer.TimerFactoryBean">
        <property name="scheduledTimerTasks">
            <list>
                <ref local="testTask" />
            </list>
        </property>
    </bean>

      使用ScheduledExecutorService时,配置如下

	<bean id="testTask" class="org.springframework.scheduling.concurrent.ScheduledExecutorTask">
         <property name="runnable">
            <ref bean ="timer"/>
         </property>
         <property name="period">
            <value>120000</value>
         </property>
         <property name="delay">
            <value>0</value>
         </property>
         <property name="fixedRate">
             <value>true</value>
         </property>
    </bean>
	<bean class="org.springframework.scheduling.concurrent.ScheduledExecutorFactoryBean">
        <property name="scheduledExecutorTasks">
            <list>
                <ref local="testTask" />
            </list>
        </property>
    </bean>