一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

Builder.com.cn - 編程 - 在Spring中使用JDK Timer進(jìn)行任務(wù)...

 ShangShujie 2007-05-29

概述

在JDK 1.3以后的版本中,Java通過java.util.Timer和java.util.TimerTask這兩個(gè)類提供了簡單的任務(wù)調(diào)度的功能,我們稱之為JDK Timer。

JDK Timer允許按照固定頻率重復(fù)執(zhí)行某項(xiàng)任務(wù),這比直接通過編寫底層線程程序進(jìn)行任務(wù)調(diào)度要輕松許多,但是對于諸如“在每周一10:00執(zhí)行任務(wù)”這種日歷相關(guān)的任務(wù)調(diào)度需求來說,JDK Timer就難以應(yīng)付了。

此外,JDK Timer只適合對執(zhí)行時(shí)間非常短的任務(wù)進(jìn)行調(diào)度,因?yàn)樵赥imer中所有TimerTask都在同一背景線程中執(zhí)行,長時(shí)間的任務(wù)會嚴(yán)重影響到Timer的調(diào)度工作。

了解Timer和TimerTask

TimerTask代表一個(gè)需要多次執(zhí)行的任務(wù),它實(shí)現(xiàn)了Runnable接口,可以在run()方法中定義任務(wù)邏輯。而Timer負(fù)責(zé)制定調(diào)度規(guī)則并負(fù)責(zé)調(diào)度TimerTask。

TimerTask

TimerTask相當(dāng)于Quartz中Job,代表一個(gè)被調(diào)度的任務(wù)。兩者最主要區(qū)別在于:每當(dāng)執(zhí)行任務(wù)時(shí),Quartz都會創(chuàng)建一個(gè)Job實(shí)例,而JDK Timer則使用相同的TimerTask實(shí)例。所以如果TimerTask類中擁有狀態(tài),則這些狀態(tài)對于后面的執(zhí)行是可見的,從這點(diǎn)上來說,TimerTask更象是StatefulJob而非Job。TimerTask實(shí)現(xiàn)了Runnable接口,是一個(gè)抽象類,它只有以下3個(gè)方法:

abstract void run():子類覆蓋這個(gè)方法并定義任務(wù)運(yùn)行的邏輯,每次執(zhí)行任務(wù)時(shí),run()方法被執(zhí)行一次;

boolean cancel():取消任務(wù)。如果任務(wù)被安排運(yùn)行一次且任務(wù)未執(zhí)行時(shí),任務(wù)將永遠(yuǎn)不會運(yùn)行;如果任務(wù)被安排執(zhí)行多次,調(diào)用該方法后,將取消后面的執(zhí)行安排;

long scheduledExecutionTime():返回此任務(wù)最近實(shí)際執(zhí)行的安排執(zhí)行時(shí)間。如果在任務(wù)執(zhí)行過程中調(diào)用此方法,則返回值此次執(zhí)行對應(yīng)的安排執(zhí)行時(shí)間(一個(gè)任務(wù)的實(shí)現(xiàn)執(zhí)行時(shí)間和安排的計(jì)劃執(zhí)行時(shí)間并不一致)。該方法一般在run()方法內(nèi)調(diào)用,你可以通過該方法判斷本次執(zhí)行的時(shí)間點(diǎn)是否過晚,并據(jù)此決定是否要取消本次的運(yùn)行。該方法一般在固定頻率執(zhí)行時(shí)使用才會有意義。

Timer

Timer只能以這樣的方式對任務(wù)進(jìn)行調(diào)度:在延遲一段時(shí)間或在指定時(shí)間點(diǎn)后運(yùn)行一次任務(wù)或周期性的運(yùn)行任務(wù)。實(shí)際上,Timer內(nèi)部使用Object#wait(long time)進(jìn)行任務(wù)的時(shí)間調(diào)度,這種機(jī)制不能保證任務(wù)的實(shí)時(shí)執(zhí)行,只是一個(gè)粗略的近似值。

每一個(gè)Timer對象有一個(gè)對應(yīng)的“背景線程”,它負(fù)責(zé)調(diào)度并執(zhí)行Timer中所有的TimerTask。由于所有的TimerTask都在這個(gè)線程中執(zhí)行,所以TimerTask的執(zhí)行時(shí)間應(yīng)該非常短,如果一個(gè)TimerTask的執(zhí)行占用了過多的時(shí)間,后面的任務(wù)就會受到影響。由于后續(xù)任務(wù)在調(diào)度時(shí)間軸上受到了“擠壓”,可能會造成“扎堆”執(zhí)行的情況。
 

當(dāng)Timer中所有的TimerTask已經(jīng)執(zhí)行完成并且Timer對象沒有外部引用時(shí),Timer的任務(wù)執(zhí)行線程才會結(jié)束。但這可能需要很長的時(shí)間才會發(fā)生。

因此Timer在默認(rèn)情況下使用非后臺線程(daemon Thread),這樣你就可以在應(yīng)用程序中通過Timer#cancel()方法手工結(jié)束Timer。如果希望盡快結(jié)束Timer中的任務(wù),則可以調(diào)用TimerTask#cancel()方法來達(dá)到目的。

Timer的構(gòu)造函數(shù)在創(chuàng)建Timer對象的同時(shí),將啟動一個(gè)Timer背景線程,我們先來了解一下Timer的幾個(gè)構(gòu)造函數(shù):

●Timer():創(chuàng)建一個(gè)Timer,背景線程是非后臺線程;

●Timer(boolean isDaemon):創(chuàng)建一個(gè)Timer,背景線程是后臺線程,后臺線程將在應(yīng)用程序主線程停止后自動退出,該方法是JDK 5.0新增的;

●Timer(String name):和Timer()類似,只不過通過name為關(guān)聯(lián)背景線程指定了名稱;

●Timer(String name, boolean isDaemon):和Timer(boolean isDaemon)類似并為關(guān)聯(lián)背景線程指定名稱,該方法是JDK 5.0新增的。

通過以下方法運(yùn)行一次任務(wù):

●schedule(TimerTask task, Date time):在特定時(shí)間點(diǎn)執(zhí)行一次任務(wù);

●schedule(TimerTask task, long delay):延遲指定時(shí)間后,執(zhí)行一次任務(wù),delay的單位為毫秒。

通過以下方法按固定時(shí)間間隔周期性運(yùn)行任務(wù),任務(wù)的執(zhí)行可能產(chǎn)生時(shí)間的漂移:

●schedule(TimerTask task, Date firstTime, long period):從指定時(shí)間點(diǎn)開始周期性執(zhí)行任務(wù),period的單位為毫秒,后一次的執(zhí)行將在前次執(zhí)行完成后才開始計(jì)時(shí)。如任務(wù)被安排2秒鐘運(yùn)行一次,當(dāng)?shù)谝淮芜\(yùn)行花費(fèi)了1.5秒時(shí),第二次將在3.5秒時(shí)運(yùn)行。所以這種任務(wù)調(diào)度是固定時(shí)間間隔;

●schedule(TimerTask task, long delay, long period):延遲指定時(shí)間后,周期性執(zhí)行任務(wù)。

通過以下方法按固定時(shí)間間隔運(yùn)行任務(wù):

●scheduleAtFixedRate(TimerTask task, Date firstTime, long period):在指定時(shí)間點(diǎn)后,以指定頻率運(yùn)行任務(wù)。假設(shè)一個(gè)任務(wù)被安排2秒鐘運(yùn)行一次,如果第一次運(yùn)行花費(fèi)了1.5秒,則在0.5秒后,第二次任務(wù)又會開始執(zhí)行,以保證固定的執(zhí)行頻率。

●scheduleAtFixedRate(TimerTask task, long delay, long period):在延遲一段時(shí)間后以指定頻率運(yùn)行任務(wù)。

此外,Timer還擁有幾個(gè)控制方法:

●cancel():取消Timer的,并丟棄所有被調(diào)度的TimerTask,不過正在執(zhí)行的任務(wù)不受影響。Timer被取消后,不能調(diào)度新的TimerTask;

●purge():將所有已經(jīng)取消的TimerTask從Timer列隊(duì)中清除,如果TimerTask沒有外部的引用,就可以被垃圾回收了。一般情況下無需調(diào)用該方法,只有在某些特殊情況下,當(dāng)一次性取消多個(gè)TimerTasks后,調(diào)用該方法才有意義。
 

JDK Timer實(shí)例

首先創(chuàng)建一個(gè)任務(wù),并在運(yùn)行10次以后退出運(yùn)行,代碼如下:

package com.baobaotao.basic.timer;

import java.util.Date;

import java.util.TimerTask;

public class SimpleTimerTaskextends TimerTask{

private int count = 0;

public void run() {

System.out.println("execute task.");

Date exeTime = (new Date(scheduledExecutionTime()));①獲取本次安排執(zhí)行的時(shí)間點(diǎn)

System.out.println("本次任務(wù)安排執(zhí)行時(shí)間點(diǎn)為:"+exeTime);

if(++count > 10)② 在任務(wù)運(yùn)行10次后主動退出運(yùn)行

}

}

通過擴(kuò)展TimerTask并實(shí)現(xiàn)run()抽象方法定義一個(gè)任務(wù)。在JDK Timer中沒有指定運(yùn)行特定次數(shù)任務(wù)的方法。你可以在任務(wù)的run()方法中通過自定義代碼實(shí)現(xiàn)。

下面通過Timer以固定延遲時(shí)間的方式每5秒執(zhí)行一次任務(wù):

package com.baobaotao.basic.timer;

import java.util.Timer;

import java.util.TimerTask;

public class TimerRunner {

public static void main(String[] args) {

Timer timer = new Timer();

TimerTask task = new SimpleTimerTask();

timer.schedule(task,1000L,5000L); ①在延遲1秒鐘后,每5秒鐘運(yùn)行一次任務(wù)

}

}

運(yùn)行以上代碼,將輸出以下信息:

execute task.

本次任務(wù)安排執(zhí)行時(shí)間點(diǎn)為:Thu Mar 15 18:39:37 CST 2007

execute task.

本次任務(wù)安排執(zhí)行時(shí)間點(diǎn)為:Thu Mar 15 18:39:42 CST 2007

execute task.

本次任務(wù)安排執(zhí)行時(shí)間點(diǎn)為:Thu Mar 15 18:39:47 CST 2007

Spring對JDK Timer的支持

Spring在org.springframework.scheduling.timer中提供了幾個(gè)JDK Timer的支持類,主要在以下三方面對JDK Timer提供了支持:

1) ScheduledTimerTask,它對TimerTask提供封裝并或配置調(diào)度信息;

2)通過MethodInvokingTimerTaskFactoryBean類可以將一個(gè)Bean的方法封裝為TimerTask;

3)通過TimerFactoryBean可以更方便地配置Timer,此外讓Timer的生命周期和Spring容器的生命周期相關(guān),在初始化TimerFactoryBean后,啟動Timer,在Spring容器關(guān)閉前取消Timer。

使用ScheduledTimerTask

JDK Timer標(biāo)準(zhǔn)的API要求我們使用Timer方法進(jìn)行任務(wù)調(diào)度時(shí)才指定調(diào)度的規(guī)則,這種方式不太適合進(jìn)行Bean的配置,因此Spring提供了ScheduledTimerTask,通過屬性指定任務(wù)和調(diào)度規(guī)則,請看下面的代碼:

<bean id="timerTask"class="com.baobaotao.basic.timer.SimpleTimerTask" />

<bean id="scheduledTask"class="org.springframework.scheduling.timer.ScheduledTimerTask">

<property name="timerTask" ref="timerTask" />指定調(diào)度任務(wù)

<property name="delay" value="1000" />延遲時(shí)間,單位為毫秒

<property name="period" value="1000" />周期時(shí)間,單位為毫秒

</bean>

如果只希望運(yùn)行一次任務(wù),將period設(shè)置為0或負(fù)值。默認(rèn)情況下,采用固定時(shí)間間隔的調(diào)度方式,可以通過fixedRate屬性,以固定頻率的方式運(yùn)行任務(wù)。SimpleTimerTask還可以將實(shí)現(xiàn)了Runnable接口的類封裝成一個(gè)任務(wù),你可以通過runnable屬性進(jìn)行設(shè)置。

MethodInvokingTimerTaskFactoryBean

類似于Quartz的MethodInvokingJobDetailFactoryBean,Spring也為JDK Timer提供了一個(gè)方便類用以將Bean方法封裝成一個(gè)TimerTask:

<bean id="myService" class="com.baobaotao.service.MyService" />

<bean id="timerTask1"① 將返回一個(gè)TimerTask實(shí)例

class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">

<property name="targetObject" ref="myService" />② 業(yè)務(wù)Bean

<property name="targetMethod" value="doJob" /> 業(yè)務(wù)方法

</bean>

TimerFactoryBean

類似于Quartz的SchedulerFactoryBean,Spring為Timer提供了TimerFactoryBean類。你可以將多個(gè)ScheduledTimerTask注冊到TimerFactoryBean中,TimerFactoryBean將返回一個(gè)Timer實(shí)例。在TimerFactoryBean初始化完成后,對應(yīng)的Timer啟動,在Spring 容器關(guān)閉之前,TimerFactoryBean將取消Timer。請看下面的配置代碼:

<bean id="timer"class="org.springframework.scheduling.timer.TimerFactoryBean">

<property name="scheduledTimerTasks">

<list>

<ref bean="scheduledTask" />

</list>

</property>

</bean>

scheduledTimerTasks屬性的類型為ScheduledTimerTask[],可以注入多個(gè)ScheduledTimerTask。此外TimerFactoryBean還擁有一個(gè)daemon屬性,指定生成Timer的背景線程是否為后臺線程。

小結(jié)

JDK Timer可以滿足一些簡單的任務(wù)調(diào)度需求,好處就是你不必引用JDK之外的第三方類庫,學(xué)習(xí)也很簡單。

但你必須保證你的任務(wù)是短小型的任務(wù),任務(wù)應(yīng)該很快就能執(zhí)行完成,否則將產(chǎn)生“時(shí)間漂移”的問題。此外,使用JDK Timer的任務(wù)對執(zhí)行時(shí)間點(diǎn)應(yīng)該沒有嚴(yán)格的要求,因?yàn)镴DK Timer只能做到近似的時(shí)間安排。

 

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    深夜福利欲求不满的人妻| 91欧美日韩国产在线观看| 国产91人妻精品一区二区三区| 亚洲国产日韩欧美三级| 日本高清一道一二三区四五区 | 国产偷拍盗摄一区二区| 一区二区福利在线视频| 美国欧洲日本韩国二本道| 午夜久久久精品国产精品| 日韩精品人妻少妇一区二区| 手机在线观看亚洲中文字幕| 欧美国产日韩变态另类在线看| 国产欧美日韩视频91| 婷婷色香五月综合激激情| 99亚洲综合精品成人网色播| 黄色日韩欧美在线观看| 欧美精品一区二区水蜜桃| 欧美日韩国产二三四区| 亚洲中文字幕在线视频频道| 中文字幕乱码免费人妻av| 丝袜视频日本成人午夜视频| 日韩在线中文字幕不卡| 日韩一区二区三区嘿嘿| 91人妻人人做人碰人人九色| 免费观看一区二区三区黄片| 国产精品一区欧美二区| 国产伦精品一一区二区三区高清版| 熟女中文字幕一区二区三区| 色偷偷偷拍视频在线观看| 久热这里只有精品九九| 国产亚洲欧美一区二区| 深夜福利亚洲高清性感| 亚洲国产天堂av成人在线播放| 亚洲精品福利视频在线观看| 日本在线 一区 二区| 激情综合网俺也狠狠地| 国产一区二区三区午夜精品| 国产精品福利精品福利| 亚洲国产av精品一区二区| 国产亚洲午夜高清国产拍精品| 国产一区二区不卡在线播放 |