2012-05-30 14 views
3

我似乎無法弄清楚如何在java中製作一個簡單的定時器。我需要的只是顯示時間,真的。所以只是一個開始的方法,它會繼續像0:00,0:01,0:02等數字。我已經看到了一些其他類似的論壇帖子,但所有的代碼是一種複雜的我的水平理解;我對Java很陌生。但是,製作一個只執行這種基本功能的計時器應該很難嗎?如果有人可以幫助它將不勝感激:)在Java中製作一個簡單的定時器

+1

帶顯示器的計時器將涉及線程。如果你不熟悉Java,或者一般編程,我建議在深入研究線程之前先學習更簡單的東西。 – kevin628

+0

這樣的計時器不一定涉及線程。如果您已經有一個事件循環,則可以使用相同的現有循環。如果程序是一個命令行電傳類型的程序,那麼前臺(主)線程可以工作。而且,如果你有一個GUI程序,你只需要確保屏幕刷新的次數比用戶看起來更頻繁,而且可以使用GUI定時器功能來完成。你不應該假設需要線程。 – AgilePro

回答

17

這並不難。但是,我會告誡你,我已經看到了堆棧溢出的一些非常混淆的答案,在某些情況下,編碼習慣令人震驚,所以要非常小心。首先讓我回答這個問題。

如果看起來程序員在實現計時器時犯的最大錯誤是認爲他們需要一些東西來跟蹤當前時間。也就是說,他們編寫了一些循環,每秒鐘增加一個變量或一些這樣的愚蠢的東西。您不需要編寫代碼來跟蹤時間。功能System.currentTimeMillis()將爲您做到這一點,它相當準確。

定時器代碼將涉及到兩個方面,許多程序員混合起來:

  1. 的時間計算
  2. 刷新顯示屏的

所有你需要做的,計算時間顯示,是記錄計時器啓動的時間:

long startTime = System.currentTimeMillis(); 

後來,當你想顯示的時間量,你只需從當前時間中減去。

long elapsedTime = System.currentTimeMillis() - startTime; 
long elapsedSeconds = elapsedTime/1000; 
long secondsDisplay = elapsedSeconds % 60; 
long elapsedMinutes = elapsedSeconds/60; 
//put here code to format and display the values 

程序員犯的最大錯誤就是認爲他們需要一個變量來保存當前的時間,然後編寫代碼來增加該變量每一秒,例如他們所維護的東西叫做「elapsedSeconds」。問題是你可以調度每秒調用一次的代碼,但不能保證代碼被調用的時間。如果系統繁忙,那麼該代碼可能比第二個代碼晚得多。如果系統非常忙碌(例如從故障磁盤讀取頁面),實際上可能會晚幾秒。使用Thread.sleep(1000)函數每秒循環的代碼會發現隨着時間的推移,錯誤會逐漸增加。如果睡眠一次延遲300ms,那麼這個錯誤就會被計算在你的時間計算中。這完全沒有必要,因爲操作系統具有告訴你當前時間的功能。

無論您每秒運行一次該代碼,每秒執行100次還是每3.572秒運行一次,上述計算都將是準確的。關鍵是,currentTimeMillis()是時間的準確表示,無論何時調用此代碼 - 這是一個重要的考慮因素,因爲線程和計時器事件在特定時間不能保證準確。

定時器的第二個方面是刷新顯示。這將取決於您使用的顯示技術。在GUI環境中,您需要安排繪畫事件。您希望這些繪畫事件在顯示器預計發生更改之後立即到來。然而,這很棘手。您可以請求繪畫事件,但可能會有數百個其他繪畫事件排隊等待處理。

一個懶惰的方法是每秒安排10個繪畫事件。因爲時間的計算不依賴於在特定時間點被調用的代碼,並且因爲如果用同一時間重新繪製屏幕並不重要,這種方法或多或少地確保顯示的時間將會在大約1/10秒內顯示正確的時間。這看起來有點浪費,因爲10次中有9次你正在畫屏幕上的東西。

如果您正在編寫一個帶有某種動畫(如遊戲)的程序,每秒刷新一次屏幕30次,那麼您無需執行任何操作。只需將計時器顯示呼叫合併到常規屏幕刷新中即可。

如果油漆事件是昂貴的,或者如果你正在編寫一個程序,它終端風格的輸出,可以通過計算的剩餘時間顯示將改變量優化事件的調度:

long elapsedTime = System.currentTimeMillis() - startTime; 
long timeTillNextDisplayChange = 1000 - (elapsedTime % 1000); 

變量timeTillNextDisplayChange保存了您需要等待的時間(以毫秒爲單位),直到計時器的秒數部分發生變化。然後,您可以安排繪畫事件發生在那個時候,可能調用Thread.sleep(timeTillNextDisplayChange)並在睡眠後輸出。如果您的代碼在瀏覽器中運行,則可以使用此技術在正確的時間更新頁面DOM。

請注意,計算刷新的計算中沒有任何內容會影響計時器本身的準確性。該線程可能從晚睡10ms,甚至晚睡500ms,並且定時器的準確性不會受影響。在每一次通過時,我們都會計算從currentTimeMillis等待的時間,因此一次遲到被調用不會導致稍後的顯示延遲。

這是準確定時器的關鍵。不要指望操作系統調用你的例程,或者在你要求時發送繪畫事件。當然,通常情況下,對於現代化的機器,操作系統反應靈敏且準確。這發生在你沒有運行其他許多測試的情況下,並且計時器似乎工作。但是,在生產中,在罕見的壓力情況下,您不希望計時器「漂流」,因爲系統很忙。

相關問題