我創建了一個多線程應用程序,它使用相同的ScheduledExecutorService(方法scheduleAtFixedRate和一個固定的10個線程的線程池)執行不同的任務。然而,除了一個主要任務之外的所有線程(不要與主線程混淆!)大部分時間都在睡覺,直到有用戶輸入。主任務和其他(用戶輸入)線程之間共享的數據受同步塊中的鎖對象保護。Java ScheduledExecutorService - 需要關於實時性能問題的建議
主要任務以相當大的頻率執行重複任務,例如25赫茲(即40毫秒的週期),重要的是及時執行此任務。通常情況也是如此,但不幸的是並非全部。其他「很好」的應用程序也運行在同一臺計算機上(Linux OP),但是CPU 100%運行在100%以上。在60分鐘的測量期間(即90000個樣品),在約50個樣品中,兩個連續樣品之間的實際週期>≥60ms,並且其中約30個週期超過100ms,在幾個非常差的病例(時間相當接近,以秒爲單位),時間在1000到2300毫秒之間。在測量過程中沒有用戶輸入。看看數據日誌,看起來很明顯,有些東西阻止執行程序在這些時間間隔內執行其工作,因爲它們通常跟着執行程序的「追趕」,即在2或3毫秒內從應用程序中獲取多個日誌。
我已經嘗試過在每次執行任務時定期進行垃圾回收,但是(至少從短期來看)它似乎只會讓事情變得更糟。我也測量了任務的執行時間。它大部分是大約1毫秒,它不應該導致執行器崩潰(或者應該這樣做?)。在這裏也有的偏差,偶爾也會在100ms左右,但他們可以解釋不到50%的延遲。我試過尋找TaskRejectedExceptions,什麼都沒發現。
所以我現在的問題基本上是:我可以期待從一個ScheduledExecutorService隨着時間的推移?這可能是一個線程問題,儘管在這些情況下只有主要任務應該運行嗎?什麼可能會導致ScheduledExecutor暫時停止執行,只能用它的「追趕」數據來洪泛日誌,並且是否有任何方法來控制這種惱人的行爲?這可能與我的JVM僅僅是沒有實時優先級功能的普通JVM有關嗎?任何關於從哪裏開始挖掘的幫助,想法或理論,都會得到真正的讚賞!
我相信你沒有通過任務的記錄時間來判斷任務的執行時間,而是明確地測量並打印出調用之間的時間? – Perception 2012-02-02 22:35:32
這有點令人困惑。所以你所說的測量是兩次執行主任務的動作之間的時間,應該每40ms執行一次。 – Tudor 2012-02-02 22:36:19
很難說,但日誌和垃圾回收可以大量影響'及時'的性能。要專注於日誌記錄,您可能不應該在執行程序的某個線程中運行任何日誌記錄代碼。控制GC出現並不在我的聯盟中,並且高度依賴於您正在使用的JVM。最好的一般技巧是儘量減少對象的創建,但當GC中斷你的應用程序時(除非你精確地定製你的應用程序和JVM設置),*會*得到一個點。 – 2012-02-02 22:39:37