2011-09-07 4 views
4

Androidアプリケーションの(UI以外の)スレッドのタイミングイベントを生成していますが、これらのイベントが正確な時間間隔で発生する必要がありますここでは+/- 5ミリ秒を超えて変化しないことを意味する)。 +/- 10ミリ秒(および確かに+/- 20ミリ秒)の誤差は、ユーザが知覚することができる。このループの最上部では、さまざまな時間を取る計算をいくつか行いますが、ループの最後には、事前に計算された時間にイベントが発生する必要があります。AndroidでThread.sleep()の遅延を減らす方法

私の非UIスレッドで1回の試行(例外処理なし)A higly簡易版は、以下の通りです:

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は、10分の1ミリ秒で計測されます。現在時刻を測定する式(System.nanoTime()/100000L)も同様に10分の1ミリ秒である。

私はcalcutionsTakingVaryingAmountOfTime()は常に未満200 millisecsをとり、listener.onEvent()への呼び出しは、わずか数millisecsであることを絶対に確信しています。ですから、loopTime2500Lに設定すると、私の出来事は250ミリ秒ごとに発生するはずです。

Thread.sleep()ウェイクアップ時間の待ち時間をLog.d()に出力するために私のコード(図示せず)を組み立てました。それは私がすぐにThread.sleep()からの復帰後

long latency = (System.nanoTime()/100000L) - eventTime 

を計算し、Log.d()にそれを印刷し、です。

これをエミュレータで実行すると、latency(結果をミリ秒にするために10で除算した後)は通常、ループを連続して通過する際に1から50ミリ秒の間にジャンプし、半分の秒として。実際のデバイスで実行すると、ややこしいですが、少しでも揺れています(さらに、エミュレータの動作によってユーザーのデバイスでこの問題が発生するかどうか疑問に思うかもしれません)。

私のイベントを安定して、待ち時間を制御しようとするが、私は他のいくつかのアプローチを試してみました:

  • ではthis.wait(eventWait/10L)(待ち時間の完全に不適切な使用()を呼び出して、Thread.sleep(eventWait/10L)コールを置き換え、I

  • 私はProcess.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO)はアンドロイドのライブラリ上のすべての行われている好きな呼び出し、ループに入る前に、スレッドの優先順位を操作する)知っている

しかし、これらのレイテンシには何の改善もありませんでした。

while ((System.nanoTime()/100000L) < eventTime) 
    ; 

1オン:

イベントをsteadysず、2またはmillisecs 3未満に待ち時間を短縮し、めったにしゃっくり一つのアプローチは、ポーリングループによってThread.sleep()コールを交換することです私は自由に酔っている船員のような忙しい消費マシンサイクルを感じています。一方、私は良い方法がないと思うようになり始めています。待ち時間を短縮し、仕様を満たすためにマシンサイクルをポーリングループで焼くべきです。もちろん、私のアプリがバックグラウンドに行くと、私はスレッドを一時停止するので、このポーリングループが機能します。しかし、何が無駄です。

アイデアをいただければ幸いです。

答えて

2

同様の目的で、Handlerの遅延メッセージを使用しています。それは少し過度なことができます。あなたの場合、私はTimerクラスを見ていきます。

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

これにより、エミュレータでのレイテンシが-2ミリ秒になります。

+0

ありがとうございます。私はいくつかのことを試しました。最初に、 'Thread.sleep()'への呼び出しの代わりに(多かれ少なかれ)dropとして 'java.util.Timer.schedule(TimerTask task、long delay)'の呼び出しを使用しようとしました。それは – singerofwords

+0

のようなものでしたあなたの提案をありがとう。私はいくつかのことを試しました。最初に、 'Thread.sleep()'への呼び出しの代わりに(多かれ少なかれ)dropとして 'java.util.Timer.schedule(TimerTask task、long delay)'の呼び出しを使用しようとしました。それから、あなたのように 'scheduleAtFixedRate()'を使ってみました。いずれの場合も、エミュレータの待ち時間は1〜70ミリ秒ですが、デバイスの待ち時間はほぼ仕様になっています。エミュレータで+/- 2ミリ秒のレイテンシを得るために他に何かしていますか? – singerofwords

+0

私は小さなテストアプリしか走らなかったので、ストレスはほとんどありませんでした。私のCPUはIntel(R)Core(TM)2 Duo CPU T9300 @ 2.50GHzです。 – Salw

関連する問題