多線程之----定時器TIMER

結上一篇  多線程的簡單介紹  http://www.cnblogs.com/duanxiaojun/p/6595847.htmlhtml

在上一講中我主要是對多線程學習這個系列作了一個大體的學習計劃,而後對實現線程的兩種方式作了介紹,可是在上一講中漏說了一點就是爲何java要提供集成Thread和實現runnable接口這兩種方式來實現線程,這個問題是我在面試的時候被問到的,很惋惜以前從沒了解過爲何-------這也給本身一個教訓就是之後學什麼東西要試着去問本身爲何是這樣的,人家爲何這樣去設計。好了針對這個問題在我查閱了不少資料後得出的是以下的解釋:java

首先說一下,咱們知道java的集成只能是單繼承,不能多集成,這樣的話就會有缺陷,好比想增長一個功能的時候必需要去修改基類。而實現runnable接口的這種方式能夠很好的解決java不能多繼承致使的缺陷。這是第一個緣由。面試

再說第二個,咱們知道實現runnable接口的方式代碼的寫法是這樣的:new Thread(new runnable(){ public void run(){    ....}})。在這種狀況下咱們能夠看到其實整個的runnable對象中的代碼能夠被多個Thread對象實例所使用共享,這樣就能夠解決一個多個線程處理同一資源的狀況。作到了線程安全。在這裏我覺着有必要經過一個代碼的方式來解釋一下第二個優勢是如何實現的。咱們拿一個賣火車票的例子,固然也能夠是其餘的有惟一資源的例子均可以。下面先看代碼以下和對代碼的解釋:安全

上面第對這個優勢的一個代碼的展現。多線程

好了 除了這兩個外 咱們說其實在真正的項目中咱們使用實現接口的方式是比較多的。函數

說到這裏好像沒有說線程的一些狀態,線程有以下的幾種狀態:建立,就緒,堵塞,終止。對這四種狀態你們應該比較熟悉吧,這時候我又想起來一個面試的時候被問的,就是說說sleep和wait有什麼區別,其實從字面意思也不難理解,sleep是睡眠,睡指定時候後就本身到就緒隊列中等待這cpu時間片的輪詢到的時候就佔用cpu資源開始執行。而wait是等待,知道有人去主動的喚醒他notify或者喚醒所有notifyAll,在等待的時候是不佔用資源的,也就是資源已經被釋放。其餘的我想應該沒什麼別的了。主要是看面試官想問什麼了。學習

     好了上面是對上一篇的一個總結和補充,下面開始今天的有關javaTimer定時器的學習。線程

首先來講一下Timer是怎麼工做的,Timer 是按照必定的時間段或者一個時間點根據定時的定時任務進行執行的。設計

Timer這個java提供的定時器有以下的特色:htm

① 他是一個單線程的,也就是你啓動一個Timer定時器就是啓動了一個線程。

② Timer定時器默認的狀況下不是守護線程,可是能夠經過構造參數設置爲守護線程,守護線程在沒有其餘線程的狀況下本身會掛掉。

③ 使用Timer定時器的時候 要跟一個TimerTask定時任務結合來使用。並且TimerTask其實底層就是一個隊列,在TimerTask中增長的任務會在定時器這個線程裏面挨個的執行。TimerTask也有本身的cannel取消等方法。

④ TimerTask中的run方法沒法拋出,因此要進行try catch捕獲,若是其中任何一個任務發生異常沒有被捕獲,則其餘任務也將被終止

說了這些概念,咱們先來一個代碼例子來看看是這麼執行的吧。

咱們看到TImer定時器這個類有兩個schedule方法。其中都有的就是一個TimerTask這個任務。我對這兩個方法進行了一個總結-----網友提供。。

方法詳解:
(1)schedule(TimerTask task, Date executeTime)
當executeTime<=currentTime時,task任務會在currentTimer當即執行
當executeTime>currentTime時,task會在將來的executeTime執行
 
(2)schedule(TimerTask task, Date firstTime, long period)
當firstTime <=currentTime時,task任務會在currentTimer當即執行,
當firstTime >currentTime時,task會在將來的executeTime執行,
執行任務所用的時間taskUsedTime<peroid,則下一個任務執行的時間是上次任務執行完成的時間+peroid,任務按時間間隔peroid週期性執行任務
執行任務所用的時間taskUsedTime>peroid,則下一個任務執行的時間是上次任務執行完成的時間+taskUsedTime,任務按時間間隔taskUsedTime 週期性執行任務
 
 
(3)schedule(TimerTask task, long delay)
任務延遲delay毫秒進行執行
 
(4)schedule(TimerTask task, long delay, long period)
A、延遲delay毫秒第一次執行,
B、執行任務所用的時間taskUsedTime<peroid,則下一個任務執行的時間是上次任務執行完成的時間+peroid, 任務按時間間隔peroid週期性執行任務
C、執行任務所用的時間taskUsedTime>peroid,則下一個任務執行的時間是上次任務執行完成的時間+taskUsedTime, 任務按時間間隔taskUsedTime 週期性執行任務
 
(5)scheduleAtFixedRate(TimerTask task, long delay, long period)
 
(6)scheduleAtFixedRate(TimerTask task, Date firstTime,  long period)
         startTime = currentTime
A、當firstTime>currentTime,任務則在currentTime執行
B、當firstTime<currentTime,任務會發生追趕執行,追趕執行的次數expectCount=(currentTime-firstTime)/peroid+1;
  第一個peroid屬於追趕階段,若是追遇上則等待執行startTime+peroid時間任務,若是沒有追遇上則直接執行startTime+peroid時間的任務
 
對於Timer這個定時器的使用,我想掌握到這裏就差很少了。可是仍是接上一個的話題,我要知道java在實現這個定時器的時候究竟是怎麼作的呢,哪就讓咱們去看看源碼吧,

 首先咱們看一下Timer這個類的構造函數,由於咱們知道咱們再使用Timer這個類的時候咱們只是建立了一個Timer對象,並無像Thread那樣主動的去調用start方法。因此我想答應也應該明白咱們定時器的啓動是在構造函數中作的,沒錯,從源碼中咱們能夠得道驗證:

哈哈哈  沒錯吧,其實咱們是Timer是一個單獨的線程,從第152行咱們就能夠看到,咱們能夠設置線程的名稱,能夠設置是不是守護線程,而後調用start方法定時器就起做用了。可是並不會當即執行。線程調用start後也不會當即執行,這在上一篇中已經有說到了,他實際上是把當前的線程示例放到了一個線程組中等待被執行。

哪咱們就看他是如何調度的也就是schdule是如何執行的呢。

 

 

 這裏咱們補充一下,queue是一個TaskQueue,

好了對Timer的介紹今天就到這裏吧,若有沒有說到的請各位評論一下,你們一塊學習。

相關文章
相關標籤/搜索