我在Android應用程序的(非UI)線程的循環中生成了計時事件,並且我需要這些事件以精確的時間間隔發生(精確這意味着不超過+/- 5毫秒)。用戶可以感受到+/- 10毫秒(當然是+/- 20毫秒)的任何誤差。在這個循環的頂部,我做了一些其他計算需要花費不同的時間,但是在循環的底部,我需要事件發生在預先計算的時間。如何減少Android中的Thread.sleep()延遲
一個higly的簡化版本(無異常處理)在我的非UI線程一個嘗試低於:
public final void run() {
long loopTime = 2500L;
long eventTime = (System.nanoTime()/100000L) + loopTime;
while (true) {
calcutionsTakingVaryingAmountOfTime(); // takes 200 millisecs or less
long eventWait = eventTime - (System.nanoTime()/100000L);
Thread.sleep(eventWait/10L);
listener.onEvent();
eventTime = eventTime + loopTime;
}
}
這是一個需要精確定時到listener.onEvent()
呼叫。
在上面的示例中,時間變量loopTime
,eventTime
和eventWait
以十分之一毫秒爲單位測量時間。表達式(System.nanoTime()/100000L)
測量當前時間同樣是十分之一毫秒。
我絕對可以肯定,calcutionsTakingVaryingAmountOfTime()
總是只需不到200米的毫秒,並調用listener.onEvent()
是短短的毫秒。因此,我的事件應該每250毫秒發生loopTime
設置爲2500L
。
我已經將我的代碼(未顯示)打印到Log.d()
的喚醒時間Thread.sleep()
的延遲。也就是說,我計算
long latency = (System.nanoTime()/100000L) - eventTime
從Thread.sleep()
後立即返回,並打印到Log.d()
。
當我在模擬器中運行它時,我發現latency
(除以10得到結果爲毫秒)通常在連續循環中跳過1到50毫秒,偶爾的值爲高半秒鐘。當在實際設備上運行時,情況會好一些,但仍然有點搖擺(甚至仿真器行爲讓我懷疑這是否會在用戶的設備上發生)。
要儘量穩住我的事件和控制延遲,我嘗試了其他幾種方法:
在更換
Thread.sleep(eventWait/10L)
調用,通過調用this.wait(eventWait/10L)
(完全不合適的使用wait(),我知道)我操作之前進入循環的線程優先級,稱
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO)
喜歡的是在Android的庫全部完成
但是這些延遲沒有任何改善。
的一個辦法,steadys事件,並減少了等待時間小於2或3的毫秒,很少打嗝是通過輪詢循環更換Thread.sleep()
呼叫:
while ((System.nanoTime()/100000L) < eventTime)
;
在一個我感到很尷尬,像一個喝醉了的水手一樣在自由上花費機器週期。另一方面,我開始認爲沒有更好的方法,我應該在輪詢循環中刻錄機器週期以減少延遲,並符合我的規範。當然,當我的應用程序轉到後臺時,我暫停了我的線程,所以這個輪詢循環起作用。但是多麼浪費。
任何想法將不勝感激。
感謝您的建議。我嘗試了幾件事。首先,我嘗試使用'java.util.Timer.schedule(TimerTask task,long delay)'的調用作爲(或多或少)替代我的對'Thread.sleep()'的調用。它變得像 – singerofwords
感謝您的建議。我嘗試了幾件事。首先,我嘗試使用'java.util.Timer.schedule(TimerTask task,long delay)'的調用作爲(或多或少)替代我的對'Thread.sleep()'的調用。然後我嘗試使用'scheduleAtFixedRate()'和你一樣。在這兩種情況下,仿真器上的延遲都在1到70毫秒之間,儘管延遲幾乎與設備的規格相符。還有什麼事情可以讓你在模擬器上獲得+/- 2毫秒的延遲? – singerofwords
我只運行一個小測試應用程序,所以幾乎沒有任何壓力。我的CPU是Intel(R)Core(TM)2 Duo CPU T9300 @ 2.50GHz。 – Salw