2011-09-07 123 views
4

我在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,eventTimeeventWait以十分之一毫秒爲單位測量時間。表達式(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) 
    ; 

在一個我感到很尷尬,像一個喝醉了的水手一樣在自由上花費機器週期。另一方面,我開始認爲沒有更好的方法,我應該在輪詢循環中刻錄機器週期以減少延遲,並符合我的規範。當然,當我的應用程序轉到後臺時,我暫停了我的線程,所以這個輪詢循環起作用。但是多麼浪費。

任何想法將不勝感激。

回答

2

爲了類似的目的,我使用的延遲郵件爲Handler。它可能有點矯枉過正。在你的情況下,我會看看Timer類。

mTimer = new Timer(); 
mTimer.scheduleAtFixedRate(new TimerTask() { 
    @Override 
    public void run() { 
     Log.v("TEST", " tick"); 
    } 
}, 0, 250); 

這使我在模擬器的延遲+ 2毫秒。

+0

感謝您的建議。我嘗試了幾件事。首先,我嘗試使用'java.util.Timer.schedule(TimerTask task,long delay)'的調用作爲(或多或少)替代我的對'Thread.sleep()'的調用。它變得像 – singerofwords

+0

感謝您的建議。我嘗試了幾件事。首先,我嘗試使用'java.util.Timer.schedule(TimerTask task,long delay)'的調用作爲(或多或少)替代我的對'Thread.sleep()'的調用。然後我嘗試使用'scheduleAtFixedRate()'和你一樣。在這兩種情況下,仿真器上的延遲都在1到70毫秒之間,儘管延遲幾乎與設備的規格相符。還有什麼事情可以讓你在模擬器上獲得+/- 2毫秒的延遲? – singerofwords

+0

我只運行一個小測試應用程序,所以幾乎沒有任何壓力。我的CPU是Intel(R)Core(TM)2 Duo CPU T9300 @ 2.50GHz。 – Salw

相關問題