2015-11-06 16 views
2

我有一個簡單的計時器,每分鐘都會調用一個方法來進行後臺處理。它被稱爲是這樣的:Java定時器如何在脅迫下執行?

EmailSender singletonSender = new EmailSender(cog); 
timer.scheduleAtFixedRate(singletonSender, 60000, 60000); 

它接收到一個事件,檢查,看看是否有任何理由發送電子郵件每一分鐘,發送電子郵件,然後它完成。

這一切都假定系統已啓動並正在運行,並且有可用的CPU週期。如果計算機坐在那裏什麼也不做,而且處理沒有時間,這一切都很容易理解。但是當計算機過於忙碌或處於睡眠/睡眠模式時,我找不到有關這種行爲的文檔。

如果電腦睡着了會發生什麼?

經過檢查了許多令人困惑的日誌後,我終於進行了測試。打印出日誌聲明和當前時間。我把電腦在7點30分左右睡着了,大約10分鐘後把它喚醒了。這裏是日誌跟蹤:

BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:24:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:25:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:26:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:27:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:28:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:29:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:30:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:31:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:09 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:40:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:41:28 
BACKGROUND EVENTS: Processed 0 background events at Fri Nov 06 07:42:28 

這似乎發出一串「追趕」事件。換句話說,就好像它們在睡着時一直堆放在電腦中,然後一旦機器重新啓動後它們全部涌出。就好像所有的事件都是由事件產生的,但由於無法提供它們而受到阻礙,最後,當計算機啓動時,所有事件都會氾濫。

這是按照這種方式設計的嗎?顯然,這對您設計系統的方式有影響。 IT是合乎邏輯的,如果你預計每天1440個事件,你最終將獲得1440個事件。但是,如果您只是在進行後臺處理,並且每個調用都會完成所有等待的後臺工作,那麼這些額外的調用就會毫無意義。您將需要設計方法來快速處理這些額外的大量呼叫。

如果回覆通話需要一分多鐘的時間會怎麼樣?

鑑於上述證據,看起來如果電腦變得非常忙碌,可能是您的活動遲到,但您仍然可以獲得所有活動。所以如果一個事件的處理需要一分多鐘的時間,問題是:你能確定事件不會到達另一個線程嗎?換句話說:你確信你的處理程序永遠不會在最後一次調用完成之前被調用。 Timer機制試圖隱藏你被調用的線程的細節,假設所有的調用都是在單個線程上進行似乎是合理的,但是,我正在尋找明確的文檔。

我在想什麼:這是嚴格定義的一些地方?或者僅僅是當前版本實施方式的人爲因素?

+1

您可能想嘗試[ScheduledExecutorService的(https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledExecutorService.html),看看它的行爲相同。 scheduleAtFixedRate的替代方法是在每次運行結束時安排新的運行。 – assylias

回答

4

在至少Timer#scheduleAtFixedRate的Javadoc建議你觀察到的:

在固定速率執行,每個執行相對於初始執行的安排執行時間安排。 如果由於任何原因(例如垃圾回收或其他後臺活動)延遲執行,兩個或更多執行將快速連續發生以「趕上」。從長遠來看,執行的頻率將恰好是指定週期的倒數(假設系統時鐘基礎Object.wait(long)是準確的)。

+0

感謝您的發現,那回答了第一個問題。我重新提出了第二個問題來澄清,基本上我想知道這是否設計爲單線程。我懷疑它是,但不確定。 – AgilePro

+1

好的,在java文檔中找到了其他答案(gee很難:-),因此將其標記爲接受的答案。 – AgilePro