5

ScheduledThreadPoolExecutor オブジェクトを使用してタスクをスケジュールしています。私は次の方法を使用します。

public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit) 

遅延を 30 秒に設定します (遅延 = 30,000 および単位 = TimeUnit.MILLISECONDS)。タスクがすぐに実行される場合もあれば、70 秒かかる場合もあります。

ScheduledThreadPoolExecutor は CPU 固有のクロックを使用していると思います。System.currentTimeMillis()、System.nanoTime() [CPU 固有] を比較するテストを実行すると、次のように表示されます。

スケジュール: 1272637682651ms、7858346157228410ns

実行: 1272637682667ms、7858386270968425ns

差は 16ms ですが、4011374001ns (または 40,113ms)

40秒の2つのCPUクロックの間に不一致があるように見えます

Java コードでこの問題を解決するにはどうすればよいですか? 残念ながら、これはクライアント マシンであり、システムを変更することはできません。

4

1 に答える 1

2

はい、ScheduledThreadPoolExecutor が System.nanoTime() を使用するのは正しいです。また、 System.nanoTime() が特定のシステム インスタンスに依存していることも正しいです。プロセスがスケジュールと実行の間でたまたま移行した場合は、運が悪いです。(マルチ CPU システム上の CPU 間の移行は問題ではないと思いますが、問題になるのでしょうか? VM で実行していて、VM がホスト間で移行される場合は確かに問題になります)。

この場合の唯一の本当の解決策は、ScheduledThreadPoolExecutor 以外のものを使用することだと思います... ScheduledThreadPoolExecutor.now() を変更するだけでは簡単ではありません。AbstractQueuedSynchronizer$ConditionObject.awaitNanos() も System.nanoTime() を使用します。

私のプロジェクトの 1 つは、ジョブのスケジューリングにQuartzを使用していますが、そのライブラリであなたが説明した問題は見たことがありません。実装の詳細はわかりません (おそらく System.nanoTime() も使用しているだけかもしれませんが、そうではないのでしょうか?)。

于 2010-05-02T08:15:19.127 に答える