国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

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

概述

在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ù)會(huì)嚴(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都會(huì)創(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)不會(huì)運(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í)使用才會(huì)有意義。

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ù)就會(huì)受到影響。由于后續(xù)任務(wù)在調(diào)度時(shí)間軸上受到了“擠壓”,可能會(huì)造成“扎堆”執(zhí)行的情況。
 

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

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

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

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

●Timer(boolean isDaemon):創(chuàng)建一個(gè)Timer,背景線程是后臺(tái)線程,后臺(tái)線程將在應(yīng)用程序主線程停止后自動(dò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ù)又會(huì)開始執(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次后主動(dòng)退出運(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后,啟動(dòng)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啟動(dòng),在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的背景線程是否為后臺(tái)線程。

小結(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í)間安排。

 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
不用任何框架,Java 就能實(shí)現(xiàn)定時(shí)任務(wù)的 3 種方法!
定時(shí)器有幾種實(shí)現(xiàn)方式?
Java并發(fā)編程:Timer和TimerTask(轉(zhuǎn)載)
Java線程(五):Timer和TimerTask
架構(gòu)系列——定時(shí)任務(wù)中的Timer類使用簡析
高并發(fā)之——ScheduledThreadPoolExecutor與Timer的區(qū)別和簡單示例
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服