天天看點

java定時器的使用(Timer)

java定時器的使用(Timer)

1、在應用開發中,常常須要一些周期性的操作,比方每5分鐘運作某一操作等。

對于這種操作最友善、高效的實作方式就是使用java.util.Timer工具類。

private java.util.Timer timer;

timer = new Timer(true);

timer.schedule(

new java.util.TimerTask() { public void run()

{ //server.checkNewMail(); 要操作的方法} }, 0, 5*60*1000);

第一個參數是要操作的方法,第二個參數是要設定延遲的時間,第三個參

數是周期的設定,每隔多長時間運作該操作。

使用這幾行代碼之後,Timer本身會每隔5分鐘調用一遍

server.checkNewMail()方法,不須要自己啟動線程。Timer本身也是多線程同

步的,多個線程能夠共用一個Timer,不須要外部的同步代碼。

2、

(1)Timer.schedule(TimerTask task,Date time)安排在制定的時間運作指定的

任務。

(2)Timer.schedule(TimerTask task,Date firstTime ,long period)安排指定

的任務在指定的時間開始進行反複的固定延遲運作.

(3)Timer.schedule(TimerTask task,long delay)安排在指定延遲後運作指定的

任務.

(4)Timer.schedule(TimerTask task,long delay,long period)安排指定的任務

從指定的延遲後開始進行反複的固定延遲運作.

(5)Timer.scheduleAtFixedRate(TimerTask task,Date firstTime,long period)

安排指定的任務在指定的時間開始進行反複的固定速率運作.

(6)Timer.scheduleAtFixedRate(TimerTask task,long delay,long period)安

排指定的任務在指定的延遲後開始進行反複的固定速率運作.

用Java Timer API 進行時間排程開發的相關注意點

java.util這個包中能夠找到Timer和TimerTask這兩個類。Timer直接從Object

繼承,它相當于一個計時器,可以用它來指定某個時間來運作一項任務,或者

每隔一定時間間隔重複運作同一個任務。建立一個Timer後,就會生成一個線程

在背後執行,來控制任務的執行。而TimerTask就是用來實作某項任務的類,

它實作了Runnable接口,是以相當于一個線程。

怎樣實作自己的任務排程?

1、繼承TimerTask,注意TimerTask是實作Runnable接口的,是以僅僅要重載run()

方法就可以。

2、建立Timer對象,調用schedule()方法。

相關注意點分析:

1、任務排程要優先考慮實時保證

因為Java的天性,而且在開發JDK的過程中要考慮到不同平台,而不同平台的

線程排程機制是不同的,是以各種平台下JVM 的線程排程機制也是不一緻的。

進而Timer不能保證任務在所指定的時間内運作。另外因為TimerTask是實作

Runnable接口的,在TimerTask被放進線程隊列睡眠一段時間(wait)之後,

當到了指定的該喚起該TimerTask時,因為運作的确切時機取決于JVM的排程策

略和目前還有多少線程在等待CPU處理。是以就不能保證任務在所指定的時間

内運作。通常在例如以下兩種情況下導緻任務延遲運作:

(1)、有大量線程在等待運作

(2)、GC機制的影響導緻延遲

這也是為什麼在Timer API中存在兩組排程方法的原因。即:

(1)、schedule()

用固定延遲排程。使用本方法時,在任務運作中的每個延遲會傳播到興許的任

務的運作。

(2)、scheduleAsFixedRate()

用固定比率排程。使用本方法時,全部興許運作依據初始運作的時間進行排程,

進而希望減小延遲。

詳細使用哪一個方法取決于哪些參數對你的程式或系統更重要。

2、每一個Timer對象要在背景啟動一個線程。這樣的性質在一些托管的環境下不推

薦使用,比方在應用server中。由于這些線程不在容器的控制範圍之内了。

詳細Java API 中的Timer 類和TimerTask類的描寫叙述例如以下:

java.util

類Timer

java.lang.Object

java.util.Timer

public class Timer

extends Object

一種線程設施,用于安排以後在背景線程中運作的任務。可安排任務運作一次,

或者定期反複運作。

與每一個Timer 對象相相應的是單個背景線程,用于順序地運作全部計時器任務。

計時器任務應該迅速完畢。假設完畢某個計時器任務的時間太長,那麼它會“獨

占”計時器的任務運作線程。是以,這就可能延遲興許任務的運作,而這些任務

就可能“堆在一起”,而且在上述令人讨厭的任務終于完畢時才可以被高速連續

地運作。

對Timer 對象最後的引用完畢後,而且全部未處理的任務都已運作完畢後,計

時器的任務運作線程會正常終止(而且成為垃圾回收的對象)。可是這可能要非常

長時間後才發生。預設情況下,任務執行線程并不作為守護線程來執行,是以

它可以阻止應用程式終止。假設調用方想要高速終止計時器的任務運作線程,那

麼調用方應該調用計時器的cancel 方法。

假設意外終止了計時器的任務運作線程,比如調用了它的stop 方法,那麼全部

以後對該計時器安排任務的嘗試都将導緻IllegalStateException,就好像調用

了計時器的cancel 方法一樣。

此類是線程安全的:多個線程能夠共享單個Timer 對象而無需進行外部同步。

此類不提供實時保證:它使用Object.wait(long) 方法來安排任務。

實作注意事項:此類可擴充到大量同一時候安排的任務(存在數千個都沒有問題)。

在内部,它使用二進制堆來表示其任務隊列,是以安排任務的開銷是O(log n),

當中n 是同一時候安排的任務數。

實作注意事項:全部構造方法都啟動計時器線程。

從下面版本号開始:

1.3

另請參見:

TimerTask, Object.wait(long)

構造方法摘要

Timer()

建立一個新計時器。

Timer(boolean isDaemon)

建立一個新計時器,能夠指定其相關的線程作為守護程式執行。

Timer(String name)

建立一個新計時器,其相關的線程具有指定的名稱。

Timer(String name, boolean isDaemon)

建立一個新計時器,其相關的線程具有指定的名稱,而且能夠指定作為守護程式運

行。

方法摘要

void cancel()

終止此計時器,丢棄全部目前已安排的任務。

int purge()

從此計時器的任務隊列中移除全部已取消的任務。

void schedule(TimerTask task, Date time)

安排在指定的時間運作指定的任務。

void schedule(TimerTask task, Date firstTime, long period)

安排指定的任務在指定的時間開始進行反複的固定延遲運作。

void schedule(TimerTask task, long delay)

安排在指定延遲後運作指定的任務。

void schedule(TimerTask task, long delay, long period)

安排指定的任務從指定的延遲後開始進行反複的固定延遲運作。

void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)

安排指定的任務在指定的時間開始進行反複的固定速率運作。

void scheduleAtFixedRate(TimerTask task, long delay, long period)

安排指定的任務在指定的延遲後開始進行反複的固定速率運作。

從類java.lang.Object 繼承的方法

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

構造方法具體資訊

Timer

public Timer()

建立一個新計時器。相關的線程不作為守護程式執行。

Thread, cancel()

public Timer(boolean isDaemon)

建立一個新計時器,能夠指定其相關的線程作為守護程式執行。假設計時器将用于

安排反複的“維護活動”,則調用守護線程,在應用程式執行期間必須調用守護線程,

可是該操作不應延長程式的生命周期。

參數:

isDaemon - 假設應該将相關的線程作為守護程式執行,則為true。

public Timer(String name)

建立一個新計時器,其相關的線程具有指定的名稱。相關的線程不作為守護程式運

name - 相關線程的名稱。

抛出:

NullPointerException - 假設name 為null。

1.5

Thread.getName(), Thread.isDaemon()

public Timer(String name,

boolean isDaemon)

方法具體資訊

schedule

public void schedule(TimerTask task,

long delay)

task - 所要安排的任務。

delay - 運作任務前的延遲時間,機關是毫秒。

IllegalArgumentException - 假設delay 是負數, 或者delay +

System.currentTimeMillis() 是負數。

IllegalStateException - 假設已經安排或取消了任務,或者已經取消計時器。

Date time)

安排在指定的時間運作指定的任務。假設此時間已過去,則安排馬上運作該任務。

time - 運作任務的時間。

IllegalArgumentException - 假設time.getTime() 是負數。

IllegalStateException - 假設已經安排或取消了任務,已經取消了計時器,或者計時

器線程已終止。

long delay,

long period)

安排指定的任務從指定的延遲後開始進行反複的固定延遲運作。以近似固定的時間

間隔(由指定的周期分隔)進行興許運作。

在固定延遲運作中,依據前一次運作的實際運作時間來安排每次運作。如

果因為不論什麼原因(如垃圾回收或其它背景活動)而延遲了某次運作,則後

續運作也将被延遲。從長期來看,運作的頻率一般要稍慢于指定周期的倒

數(假定Object.wait(long) 所依靠的系統時鐘是準确的)。

固定延遲執行适用于那些須要“平穩”執行的反複活動。換句話說,它适

用于在短期執行中保持頻率準确要比在長期執行中更為重要的活動。這包

括大多數動畫任務,如以固定時間間隔閃爍的光标。這還包含為響應人類

活動所運作的固定活動,如在按住鍵時自己主動反複輸入字元。

period - 運作各興許任務之間的時間間隔,機關是毫秒。

Date firstTime,

安排指定的任務在指定的時間開始進行反複的固定延遲運作。以近似固定的時間間

隔(由指定的周期分隔)進行興許運作。

續運作也将被延遲。在長期運作中,運作的頻率一般要稍慢于指定周期的

倒數(假定Object.wait(long) 所依靠的系統時鐘是準确的)。

固定延遲運作适用于那些須要“平穩”運作的反複運作活動。換句話說,

它适用于在短期執行中保持頻率準确要比在長期執行中更為重要的活動。

這包含大多數動畫任務,如以固定時間間隔閃爍的光标。這還包含為響應

人類活動所運作的固定活動,如在按住鍵時自己主動反複輸入字元。

firstTime - 首次運作任務的時間。

scheduleAtFixedRate

public void scheduleAtFixedRate(TimerTask task,

安排指定的任務在指定的延遲後開始進行反複的固定速率運作。以近似固定的時間

在固定速率運作中,依據已安排的初始運作時間來安排每次運作。假設由

于不論什麼原因(如垃圾回收或其它背景活動)而延遲了某次運作,則将高速

連續地出現兩次或很多其它的運作,進而使興許運作可以“追趕上來”。從長

遠來看,運作的頻率将正好是指定周期的倒數(假定Object.wait(long)

所依靠的系統時鐘是準确的)。

固定速率運作适用于那些對絕對時間敏感的反複運作活動,如每小時準

點打鐘報時,或者在每天的特定時間執行已安排的維護活動。它還适用于

那些完畢固定次數運作的總計時間非常重要的反複活動,如倒計時的計時

器,每秒鐘滴答一次,共10 秒鐘。最後,固定速率運作适用于安排多個

反複運作的計時器任務,這些任務互相之間必須保持同步。

安排指定的任務在指定的時間開始進行反複的固定速率運作。以近似固定的時間間

在固定速率運作中,相對于已安排的初始運作時間來安排每次運作。假設

因為不論什麼原因(如垃圾回收或其它背景活動)而延遲了某次運作,則将快

速連續地出現兩次或很多其它次運作,進而使興許運作可以趕上來。從長遠來

看,運作的頻率将正好是指定周期的倒數(假定Object.wait(long) 所

依靠的系統時鐘是準确的)。

器,每秒鐘滴答一次,共10 秒鐘。最後,固定速率運作适用于安排多次

cancel

public void cancel()

終止此計時器,丢棄全部目前已安排的任務。這不會幹擾目前正在運作的任務(如

果存在)。一旦終止了計時器,那麼它的運作線程也會終止,而且無法依據它安排更

多的任務。

注意,在此計時器調用的計時器任務的run 方法内調用此方法,就能夠

絕對確定正在運作的任務是此計時器所運作的最後一個任務。

能夠反複調用此方法;可是第二次和興許調用無效。

purge

public int purge()

從此計時器的任務隊列中移除全部已取消的任務。調用此方法對計時器的行為沒有

影響,可是将無法引用隊列中已取消的任務。假設沒有對這些任務的外部引用,則

它們就成為垃圾回收的合格對象。

多數程式無需調用此方法。它設計用于一些罕見的應用程式,這些程式可

取消大量的任務。調用此方法要以時間來換取空間:此方法的執行時可能

與n + c log n 呈正比,當中n 是隊列中的任務數,而c 是取消的任

務數。

注意,從此計時器上所安排的任務中調用此方法是同意的。

傳回:

從隊列中移除的任務數。

以下是TimerTask類的介紹

類TimerTask

java.util.TimerTask

全部已實作的接口:

Runnable

public abstract class TimerTask

implements Runnable

由Timer 安排為一次運作或反複運作的任務。

protected TimerTask()

建立一個新的計時器任務。

boolean cancel()

取消此計時器任務。

abstract void run()

此計時器任務要運作的操作。

long scheduledExecutionTime()

傳回此任務近期實際運作的安排運作時間。

TimerTask

run

public abstract void run()

指定者:

接口Runnable 中的run

Thread.run()

public boolean cancel()

取消此計時器任務。假設任務安排為一次執行且還未執行,或者尚未安排,則永遠

不會執行。假設任務安排為反複執行,則永遠不會再執行。(假設發生此調用時任務

正在執行,則任務将執行完,但永遠不會再執行。)

注意,從反複的計時器任務的run 方法中調用此方法絕對保證計時器任

務永遠不會再執行。

此方法能夠重複調用;第二次和以後的調用無效。

假設此任務安排為一次運作且尚未運作,或者此任務安排為反複運作,則傳回true。

假設此任務安排為一次執行且已經執行,或者此任務尚未安排,或者此任務已經取

消,則傳回false。(一般來說,假設此方法阻止發生一個或多個安排運作,則傳回

true。)

scheduledExecutionTime

public long scheduledExecutionTime()

傳回此任務近期實際運作的安排運作時間。(假設在任務運作過程中調用此方法,

則傳回值為此任務運作的安排運作時間。)

通常從一個任務的run 方法中調用此方法,以确定目前任務運作能否

充分及時地保證完畢安排活動:

public void run() {

if (System.currentTimeMillis() - scheduledExecutionTime()

>=

MAX_TARDINESS)

return; // Too late; skip this execution.

// Perform the task

}

通常,此方法不與固定延遲運作的反複任務一起使用,由于其安排運作時間同意

随時間浮動,是以毫無意義。

近期發生此任務運作安排的時間,採用Date.getTime() 傳回的格式。假設任務已開

始其首次運作,則傳回值不确定。