2

規則的な (!) 間隔で 1 秒あたり約 10000 回実行されるループを作成するにはどうすればよいですか?

( Javaのパラレルポートからの連続データ取得の複製ですが、それは見つけにくく、答えられておらず、非常に古いものです)

私は見ましたがThread.sleep(long millis)Thread.sleep(long millis, int nanos)Windows上のOracleのJ2SE仮想マシンは、指定した時間よりも常に1ミリ秒長くスリープします。さらに、nanos フィールドは、次のミリ秒単位に丸められているようです (検証済み、これは Thread.java のソース コードでハードコーディングされています)。

実験結果:

  • Thread.sleep(0)スリープしない (100% cpu)
  • Thread.sleep(1)平均1.95ミリ秒スリープ
  • Thread.sleep(2)平均 2.95ms スリープ
  • Thread.sleep(0, 0)スリープしない (100% cpu)
  • Thread.sleep(0, 1)平均1.95ミリ秒スリープ

では、一定の間隔で毎秒 500 回以上繰り返すループを作成するにはどうすればよいでしょうか?

編集:「通常の」要件を少し緩めます。最長の遅延が決定論的で 0.1ms 未満である限り、1 つの遅延が別の遅延の 4 分の 1 のように短い場合 (つまり、ジッターは問題ではありません) は大きな問題ではありません。(これはそうではありませんScheduledExecutorService

4

3 に答える 3

2

ScheduledExecutorServiceを探していると思います(使用例を参照)。

具体的には

scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)

Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.

TimeUnit.MICROSECONDS を使用します。

于 2013-01-06T13:18:10.063 に答える
0

コアを 100% に固定しても問題ない場合は、これを使用してサブマイクロ秒の間隔でかなり均等に分散されたイベントを取得できます。もちろん、これを使用して最大スループット レートに達した場合は、System.nanoTime() をコストの低いタイミング呼び出しに置き換えることが望ましいでしょう。

long nanosBetweenMessages = getSpacing();
long lastSendTime = 0l;
while (true) {
   final long curTimeNanos = System.nanoTime();
   if (curTimeNanos - lastSendTime < nanosBetweenMessages) {
       continue;
   }
   lastSendTime = curTimeNanos;
   sendEvent();
   if (done()) {
       break;
   }
}

10k/秒の要件に気付きました...現在、sendEvent() メソッドでかなりの量の計算でこれを使用しており、約 20k/秒の最大レートでプッシュしています。

于 2013-03-23T04:21:13.460 に答える
0

Java でタイミング ループが発生する場合Thread.sleep(long)、これは非常に不正確なループ方法であるため、絶対に使用しないでください。javax.swing.Timer代わりに使用してみてください。リンクはこちら。http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html

于 2013-01-06T13:21:11.497 に答える