




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第Java定時(shí)器Timer的源碼分析目錄一、TimerTask1.任務(wù)狀態(tài)2.任務(wù)屬性說明3.任務(wù)方法說明二、Timer1.sched方法2.cancel方法3.purge方法三、TaskQueue四、TimerThread通過源碼分析,我們可以更深入的了解其底層原理。
對(duì)于JDK自帶的定時(shí)器,主要涉及TimerTask類、Timer類、TimerQueue類、TimerThread類,其中TimerQueue和TimerThread類與Timer類位于同一個(gè)類文件,由Timer內(nèi)部調(diào)用。
先畫上一張圖,描述一下Timer的大致模型,Timer的模型很容易理解,即任務(wù)加入到任務(wù)隊(duì)列中,由任務(wù)處理線程循環(huán)從任務(wù)隊(duì)列取出任務(wù)執(zhí)行:
一、TimerTask
TimerTask是一個(gè)任務(wù)抽象類,實(shí)現(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;
當(dāng)一個(gè)TimerTask對(duì)象創(chuàng)建后,其初始狀態(tài)為VIRGIN;
當(dāng)調(diào)用Timer的schedule方法調(diào)度了此TimerTask對(duì)象后,其狀態(tài)變更為SCHEDULED;
如果TimerTask是一次性任務(wù),此任務(wù)執(zhí)行后,狀態(tài)將變?yōu)镋XECUTED,可重復(fù)執(zhí)行任務(wù)執(zhí)行后狀態(tài)不變;
當(dāng)中途調(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í)行時(shí)間點(diǎn)
longnextExecutionTime;
//任務(wù)執(zhí)行的時(shí)間間隔。正數(shù)表示固定速率;負(fù)數(shù)表示固定時(shí)延;0表示只執(zhí)行一次
longperiod=0;
3.任務(wù)方法說明
TimerTask中有三個(gè)方法:
run:實(shí)現(xiàn)了Runnable接口,創(chuàng)建TimerTask需要重寫此方法,編寫任務(wù)執(zhí)行代碼cancel:取消任務(wù)scheduledExecutionTime:計(jì)算執(zhí)行時(shí)間點(diǎn)
3.1.Cancel方法
cancel方法的實(shí)現(xiàn)代碼:
publicbooleancancel(){
synchronized(lock){
booleanresult=(state==SCHEDULED);
state=CANCELLED;
returnresult;
}
在cancel方法內(nèi),使用synchronized加鎖,這是因?yàn)門imer內(nèi)部的線程會(huì)對(duì)TimerTask狀態(tài)進(jìn)行修改,而調(diào)用cancel方法一般會(huì)是另外一個(gè)線程。
為了避免線程同步問題,cancel在修改狀態(tài)前進(jìn)行了加鎖操作。
調(diào)用cancel方法將會(huì)把任務(wù)狀態(tài)變更為CANCELLED狀態(tài),即任務(wù)取消狀態(tài),并返回一個(gè)布爾值,該布爾值表示此任務(wù)之前是否已是SCHEDULED已調(diào)度狀態(tài)。
3.2.scheduledExecutionTime方法
scheduledExecutionTime方法實(shí)現(xiàn):
publiclongscheduledExecutionTime(){
synchronized(lock){
return(period0nextExecutionTime+period
:nextExecutionTime-period);
}
該方法返回此任務(wù)的下次執(zhí)行時(shí)間點(diǎn)。
二、Timer
分析Timer源代碼,Timer在內(nèi)部持有了兩個(gè)成員變量:
privatefinalTaskQueuequeue=newTaskQueue();
privatefinalTimerThreadthread=newTimerThread(queue);
TaskQueue是任務(wù)隊(duì)列,TimerThread是任務(wù)處理線程。
1.sched方法
無論是使用schedule還是scheduleAtFixedRate方法來調(diào)度任務(wù),Timer內(nèi)部最后都是調(diào)用sched方法進(jìn)行處理。
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);//固定延時(shí)模式,-period
publicvoidschedule(TimerTasktask,DatefirstTime,longperiod){
sched(task,firstTime.getTime(),-period);//固定延時(shí)模式,-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){
//加鎖,避免外部其他線程同時(shí)調(diào)用cancel,同時(shí)訪問queue產(chǎn)生線程同步問題
synchronized(queue){
//如果線程已終止,拋出異常
if(!thread.newTasksMayBeScheduled)
thrownewIllegalStateException("Timeralreadycancelled.");
//加鎖,避免多線程訪問同一個(gè)任務(wù)產(chǎn)生線程同步問題
synchronized(task.lock){
//task的狀態(tài)必須為VIRGIN,否則認(rèn)為已經(jīng)加入調(diào)度或者已經(jīng)取消了,避免重復(fù)的調(diào)度
if(task.state!=TimerTask.VIRGIN)
thrownewIllegalStateException(
"Taskalreadyscheduledorcancelled");
//設(shè)置下次執(zhí)行時(shí)間點(diǎn)
task.nextExecutionTime=time;
//設(shè)置時(shí)間間隔
task.period=period;
//任務(wù)狀態(tài)變更為已調(diào)度
task.state=TimerTask.SCHEDULED;
//將任務(wù)添加到隊(duì)列中
queue.add(task);
//如果此任務(wù)是最近的任務(wù),喚醒線程
if(queue.getMin()==task)
queue.notify();
}
2.cancel方法
cancel方法一般是由外部其他線程調(diào)用,而Timer內(nèi)部的線程也會(huì)對(duì)任務(wù)隊(duì)列進(jìn)行操作,因此加鎖。
publicvoidcancel(){
synchronized(queue){
//修改線程的循環(huán)執(zhí)行標(biāo)志,令線程能夠終止
thread.newTasksMayBeScheduled=false;
//清空任務(wù)隊(duì)列
queue.clear();
//喚醒線程
queue.notify();
}
3.purge方法
當(dāng)通過TimerTask.cancel將任務(wù)取消后,Timer的任務(wù)隊(duì)列還引用著此任務(wù),Timer只有到了要執(zhí)行時(shí)才會(huì)移除,其他時(shí)候并不會(huì)自動(dòng)將此任務(wù)移除,需要調(diào)用purge方法進(jìn)行清理。
publicintpurge(){
intresult=0;
synchronized(queue){
//遍歷隊(duì)列,將CANCELLED狀態(tài)的任務(wù)從任務(wù)隊(duì)列中移除
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類文件中封裝的一個(gè)隊(duì)列數(shù)據(jù)結(jié)構(gòu),內(nèi)部默認(rèn)是一個(gè)長(zhǎng)度128的TimerTask數(shù)組,當(dāng)任務(wù)加入時(shí),檢測(cè)到數(shù)組將滿將會(huì)自動(dòng)擴(kuò)容1倍,并對(duì)數(shù)組元素根據(jù)下次執(zhí)行時(shí)間nextExecutionTime按時(shí)間從近到遠(yuǎn)進(jìn)行排序。
voidadd(TimerTasktask){
//檢測(cè)數(shù)組長(zhǎng)度,若不夠則進(jìn)行擴(kuò)容
if(size+1==queue.length)
queue=Arrays.copyOf(queue,2*queue.length);
//任務(wù)入隊(duì)
queue[++size]=task;
//排序
fixUp(size);
}
fixUp方法實(shí)現(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方法外還有一個(gè)fixDown方法,這兩個(gè)其實(shí)就是堆排序算法,在算法專題中再進(jìn)行詳細(xì)介紹,只要記住他們的任務(wù)就是按時(shí)間從近到遠(yuǎn)進(jìn)行排序,最近的任務(wù)排在隊(duì)首即可。
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),從隊(duì)列取任務(wù)執(zhí)行
while(true){
try{
TimerTasktask;
booleantaskFired;
//對(duì)任務(wù)隊(duì)列加鎖
synchronized(queue){
//如果隊(duì)列中沒有任務(wù),則進(jìn)入等待,newTasksMayBeScheduled是線程運(yùn)行標(biāo)志位,為false時(shí)將退出循環(huán)
while(queue.isEmpty()newTasksMayBeScheduled)
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年音樂教育與藝術(shù)素養(yǎng)考試試卷及答案
- 2025年證券投資與基金管理考試試題及答案
- 2025年法醫(yī)學(xué)專業(yè)考試試卷及答案
- 2025年中級(jí)職稱會(huì)計(jì)考試試題及答案
- 2025年護(hù)士職業(yè)技能考試試卷及答案
- 2025年軍事理論課程考試試卷及答案
- 2025年石油工程師考試試題及答案
- 2025年新媒體運(yùn)營(yíng)考試試卷及答案環(huán)節(jié)
- 2025年信息安全專業(yè)考試試卷及答案
- 童話動(dòng)畫角色形象授權(quán)及衍生品開發(fā)合同
- 矛盾論實(shí)踐論導(dǎo)讀課件1
- ABAQUS官方培訓(xùn)資料PPTlecture5-contact
- 任務(wù)1-安裝CPU、CPU風(fēng)扇及內(nèi)存
- 安全事故應(yīng)急響應(yīng)程序流程圖
- 勞動(dòng)力、機(jī)械設(shè)備、主要材料進(jìn)場(chǎng)計(jì)劃范文
- 07FK02 防空地下室通風(fēng)設(shè)備安裝
- 家用青飼料切割機(jī)說明書-畢業(yè)設(shè)計(jì)
- 鄭麗玲《彩墨游戲》說課x 課件
- 物品出入庫登記表
- 李世默在清華演講稿全文
- GB/T 11253-2019碳素結(jié)構(gòu)鋼冷軋鋼板及鋼帶
評(píng)論
0/150
提交評(píng)論