1.Timer類介紹:
引用JDK源碼里面的注釋就是:A facility for threads to schedule tasks for future execution in a background thread.Corresponding to each object is a single background thread that is used to execute all of the timer's tasks, sequentially. 大致意思就是:TImer是在后臺(tái)線程中用于調(diào)度未執(zhí)行任務(wù)的工具類,通俗講就是任務(wù)調(diào)度器泉瞻,相應(yīng)的每一個(gè)調(diào)取器都是一個(gè)單線程在有序的執(zhí)行指定的任務(wù)計(jì)劃。
這里需要順帶介紹一下TimeTask一個(gè)實(shí)現(xiàn)了Runable的類形纺,是一個(gè)被Timer執(zhí)行的任務(wù)類;
2.Timer簡單的demo
下面是一個(gè)簡單的demo涝焙,TImer會(huì)在5秒后輸出Timer is working 這句話俺泣;
輸出結(jié)果如下:
3.源碼分析
下面我們看源碼祥款,了解一下底層到底是怎么執(zhí)行的罗侯,首先上面我們調(diào)用了Timer的構(gòu)造函數(shù)器腋,如果是我們不傳任何參數(shù),源碼會(huì)自動(dòng)給設(shè)置一個(gè)名字钩杰,也就是會(huì)給每一個(gè)調(diào)度器一個(gè)名稱纫塌,
所有的構(gòu)造函數(shù)都會(huì)執(zhí)行上面的那個(gè)構(gòu)造函數(shù),下面我們關(guān)注一下start方法讲弄。(這里不上圖了措左,直接上代碼,我會(huì)把需要解釋的地方以注釋方式解釋)
public synchronized voidstart() {
if(threadStatus!=0)//一個(gè)全局的volatile修飾的變量垂睬,用于表示該調(diào)度器是否已經(jīng)啟動(dòng)媳荒,如果不等于0則表示已經(jīng)啟動(dòng)抗悍,這個(gè)時(shí)候會(huì)拋一個(gè)異常驹饺;
throw newIllegalThreadStateException();
group.add(this);//如果調(diào)度器狀態(tài)是未啟動(dòng),則把他添加到調(diào)度器啟動(dòng)線程組
booleanstarted =false;
try{
start0();//啟動(dòng)該調(diào)度器
started =true;
}finally{
try{
if(!started) {
group.threadStartFailed(this);//如果啟動(dòng)失敗缴渊,則把從組里面刪除赏壹,認(rèn)為無法啟動(dòng)的調(diào)度器
}
}catch(Throwable ignore) {
}
}
}
接下來我們看看schedule這個(gè)方法里面是如果實(shí)現(xiàn)的:
這個(gè)方法相對簡單,首先試試判斷時(shí)間衔沼,非法則拋異常蝌借,另外判斷是否有延時(shí),最后就是對自己實(shí)現(xiàn)的一個(gè)TaskQueue加鎖指蚁,保證線程安全菩佑,并且是有序執(zhí)行,執(zhí)行前就是對線程狀態(tài)的一些控制凝化,最后把任務(wù)調(diào)度放入隊(duì)列稍坯,等待執(zhí)行。
最后我們看看是如何終止執(zhí)行的任務(wù)呢搓劫?
這個(gè)代碼看似很簡單瞧哟,就是清空隊(duì)列,而此時(shí)你是否有疑問枪向,可線程任務(wù)是如何終止的呢勤揩?
我們回到Timer的構(gòu)造函數(shù),我們會(huì)發(fā)現(xiàn)下圖中有一個(gè)Thread對象秘蛔,而這個(gè)對象的類并不是jdk默認(rèn)的Thread類:
這個(gè)類是繼承了Thread類陨亡,而且重寫了這個(gè)方法
mainloop方法中傍衡,如果判斷queue是空的話,直接break负蠕,也就是線程執(zhí)行的任務(wù)在此終止聪舒。這樣我們就明白了cancel的操作是如何終止線程的。
4.注意點(diǎn)
因?yàn)門imer在執(zhí)行定時(shí)任務(wù)時(shí)只會(huì)創(chuàng)建一個(gè)線程虐急,所以如果存在多個(gè)任務(wù)箱残,且任務(wù)時(shí)間過長,超過了兩個(gè)任務(wù)的間隔時(shí)間止吁,會(huì)發(fā)生一些缺陷被辑。所以在任務(wù)調(diào)度多的話,執(zhí)行時(shí)間會(huì)過長敬惦,另外需要注意的是如果執(zhí)行中一個(gè)任務(wù)拋出了異常盼理,其他的任務(wù)都將會(huì)停止,所以這里還是推薦使用ScheduledExecutorService(JDK1.5以后)