Java定時器Timer的源碼分析_第1頁
Java定時器Timer的源碼分析_第2頁
Java定時器Timer的源碼分析_第3頁
Java定時器Timer的源碼分析_第4頁
Java定時器Timer的源碼分析_第5頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第Java定時器Timer的源碼分析目錄一、TimerTask1.任務(wù)狀態(tài)2.任務(wù)屬性說明3.任務(wù)方法說明二、Timer1.sched方法2.cancel方法3.purge方法三、TaskQueue四、TimerThread通過源碼分析,我們可以更深入的了解其底層原理。

對于JDK自帶的定時器,主要涉及TimerTask類、Timer類、TimerQueue類、TimerThread類,其中TimerQueue和TimerThread類與Timer類位于同一個類文件,由Timer內(nèi)部調(diào)用。

先畫上一張圖,描述一下Timer的大致模型,Timer的模型很容易理解,即任務(wù)加入到任務(wù)隊列中,由任務(wù)處理線程循環(huán)從任務(wù)隊列取出任務(wù)執(zhí)行:

一、TimerTask

TimerTask是一個任務(wù)抽象類,實現(xiàn)了Runnable接口,是可被線程執(zhí)行的。

1.任務(wù)狀態(tài)

在TimerTask中定義了關(guān)于任務(wù)狀態(tài)的常量字段:

//未調(diào)度狀態(tài)

staticfinalintVIRGIN=0;

//任務(wù)已調(diào)度,但未執(zhí)行

staticfinalintSCHEDULED=1;

//若是一次性任務(wù)表示已執(zhí)行;可重復(fù)執(zhí)行任務(wù),該狀態(tài)無效

staticfinalintEXECUTED=2;

//任務(wù)被取消

staticfinalintCANCELLED=3;

當一個TimerTask對象創(chuàng)建后,其初始狀態(tài)為VIRGIN;

當調(diào)用Timer的schedule方法調(diào)度了此TimerTask對象后,其狀態(tài)變更為SCHEDULED;

如果TimerTask是一次性任務(wù),此任務(wù)執(zhí)行后,狀態(tài)將變?yōu)镋XECUTED,可重復(fù)執(zhí)行任務(wù)執(zhí)行后狀態(tài)不變;

當中途調(diào)用了TimerTask.cancel方法,該任務(wù)的狀態(tài)將變?yōu)镃ANCELLED。

2.任務(wù)屬性說明

TimerTask中,有如下成員變量:

//用于加鎖控制多線程修改TimerTask內(nèi)部狀態(tài)

finalObjectlock=newObject();

//任務(wù)狀態(tài),初始狀態(tài)為待未調(diào)度狀態(tài)

intstate=VIRGIN;

//任務(wù)的下一次執(zhí)行時間點

longnextExecutionTime;

//任務(wù)執(zhí)行的時間間隔。正數(shù)表示固定速率;負數(shù)表示固定時延;0表示只執(zhí)行一次

longperiod=0;

3.任務(wù)方法說明

TimerTask中有三個方法:

run:實現(xiàn)了Runnable接口,創(chuàng)建TimerTask需要重寫此方法,編寫任務(wù)執(zhí)行代碼cancel:取消任務(wù)scheduledExecutionTime:計算執(zhí)行時間點

3.1.Cancel方法

cancel方法的實現(xiàn)代碼:

publicbooleancancel(){

synchronized(lock){

booleanresult=(state==SCHEDULED);

state=CANCELLED;

returnresult;

}

在cancel方法內(nèi),使用synchronized加鎖,這是因為Timer內(nèi)部的線程會對TimerTask狀態(tài)進行修改,而調(diào)用cancel方法一般會是另外一個線程。

為了避免線程同步問題,cancel在修改狀態(tài)前進行了加鎖操作。

調(diào)用cancel方法將會把任務(wù)狀態(tài)變更為CANCELLED狀態(tài),即任務(wù)取消狀態(tài),并返回一個布爾值,該布爾值表示此任務(wù)之前是否已是SCHEDULED已調(diào)度狀態(tài)。

3.2.scheduledExecutionTime方法

scheduledExecutionTime方法實現(xiàn):

publiclongscheduledExecutionTime(){

synchronized(lock){

return(period0nextExecutionTime+period

:nextExecutionTime-period);

}

該方法返回此任務(wù)的下次執(zhí)行時間點。

二、Timer

分析Timer源代碼,Timer在內(nèi)部持有了兩個成員變量:

privatefinalTaskQueuequeue=newTaskQueue();

privatefinalTimerThreadthread=newTimerThread(queue);

TaskQueue是任務(wù)隊列,TimerThread是任務(wù)處理線程。

1.sched方法

無論是使用schedule還是scheduleAtFixedRate方法來調(diào)度任務(wù),Timer內(nèi)部最后都是調(diào)用sched方法進行處理。

publicvoidschedule(TimerTasktask,Datetime){

sched(task,time.getTime(),0);//一次性任務(wù),period為0

publicvoidschedule(TimerTasktask,longdelay){

sched(task,System.currentTimeMillis()+delay,0);//一次性任務(wù),period為0

publicvoidschedule(TimerTasktask,longdelay,longperiod){

sched(task,System.currentTimeMillis()+delay,-period);//固定延時模式,-period

publicvoidschedule(TimerTasktask,DatefirstTime,longperiod){

sched(task,firstTime.getTime(),-period);//固定延時模式,-period

publicvoidscheduleAtFixedRate(TimerTasktask,longdelay,longperiod){

sched(task,System.currentTimeMillis()+delay,period);//固定速率模式,period為正

publicvoidscheduleAtFixedRate(TimerTasktask,DatefirstTime,longperiod){

sched(task,firstTime.getTime(),period);//固定速率模式,period為正

}

sched方法核心代碼:

privatevoidsched(TimerTasktask,longtime,longperiod){

//加鎖,避免外部其他線程同時調(diào)用cancel,同時訪問queue產(chǎn)生線程同步問題

synchronized(queue){

//如果線程已終止,拋出異常

if(!thread.newTasksMayBeScheduled)

thrownewIllegalStateException("Timeralreadycancelled.");

//加鎖,避免多線程訪問同一個任務(wù)產(chǎn)生線程同步問題

synchronized(task.lock){

//task的狀態(tài)必須為VIRGIN,否則認為已經(jīng)加入調(diào)度或者已經(jīng)取消了,避免重復(fù)的調(diào)度

if(task.state!=TimerTask.VIRGIN)

thrownewIllegalStateException(

"Taskalreadyscheduledorcancelled");

//設(shè)置下次執(zhí)行時間點

task.nextExecutionTime=time;

//設(shè)置時間間隔

task.period=period;

//任務(wù)狀態(tài)變更為已調(diào)度

task.state=TimerTask.SCHEDULED;

//將任務(wù)添加到隊列中

queue.add(task);

//如果此任務(wù)是最近的任務(wù),喚醒線程

if(queue.getMin()==task)

queue.notify();

}

2.cancel方法

cancel方法一般是由外部其他線程調(diào)用,而Timer內(nèi)部的線程也會對任務(wù)隊列進行操作,因此加鎖。

publicvoidcancel(){

synchronized(queue){

//修改線程的循環(huán)執(zhí)行標志,令線程能夠終止

thread.newTasksMayBeScheduled=false;

//清空任務(wù)隊列

queue.clear();

//喚醒線程

queue.notify();

}

3.purge方法

當通過TimerTask.cancel將任務(wù)取消后,Timer的任務(wù)隊列還引用著此任務(wù),Timer只有到了要執(zhí)行時才會移除,其他時候并不會自動將此任務(wù)移除,需要調(diào)用purge方法進行清理。

publicintpurge(){

intresult=0;

synchronized(queue){

//遍歷隊列,將CANCELLED狀態(tài)的任務(wù)從任務(wù)隊列中移除

for(inti=queue.size();ii--){

if(queue.get(i).state==TimerTask.CANCELLED){

queue.quickRemove(i);

result++;

//如果移除任務(wù)數(shù)不為0,觸發(fā)重新排序

if(result!=0)

queue.heapify();

//返回移除任務(wù)數(shù)

returnresult;

}

三、TaskQueue

TaskQueue是Timer類文件中封裝的一個隊列數(shù)據(jù)結(jié)構(gòu),內(nèi)部默認是一個長度128的TimerTask數(shù)組,當任務(wù)加入時,檢測到數(shù)組將滿將會自動擴容1倍,并對數(shù)組元素根據(jù)下次執(zhí)行時間nextExecutionTime按時間從近到遠進行排序。

voidadd(TimerTasktask){

//檢測數(shù)組長度,若不夠則進行擴容

if(size+1==queue.length)

queue=Arrays.copyOf(queue,2*queue.length);

//任務(wù)入隊

queue[++size]=task;

//排序

fixUp(size);

}

fixUp方法實現(xiàn):

privatevoidfixUp(intk){

while(k1){

intj=k1;

if(queue[j].nextExecutionTime=queue[k].nextExecutionTime)

break;

TimerTasktmp=queue[j];queue[j]=queue[k];queue[k]=tmp;

k=j;

}

TaskQueue中除了fixUp方法外還有一個fixDown方法,這兩個其實就是堆排序算法,在算法專題中再進行詳細介紹,只要記住他們的任務(wù)就是按時間從近到遠進行排序,最近的任務(wù)排在隊首即可。

privatevoidfixDown(intk){

intj;

while((j=k1)=sizej0){

if(jsize

queue[j].nextExecutionTimequeue[j+1].nextExecutionTime)

j++;//jindexessmallestkid

if(queue[k].nextExecutionTime=queue[j].nextExecutionTime)

break;

TimerTasktmp=queue[j];queue[j]=queue[k];queue[k]=tmp;

k=j;

voidheapify(){

for(inti=size/2;ii--)

fixDown(i);

}

四、TimerThread

TimerThread的核心代碼位于mainLoop方法:

privatevoidmainLoop(){

//死循環(huán),從隊列取任務(wù)執(zhí)行

while(true){

try{

TimerTasktask;

booleantaskFired;

//對任務(wù)隊列加鎖

synchronized(queue){

//如果隊列中沒有任務(wù),則進入等待,newTasksMayBeScheduled是線程運行標志位,為false時將退出循環(huán)

while(queue.isEmpty()newTasksMayBeScheduled)

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論