私は奇妙な問題があります - 誰かが私に何が起こっているのかを説明し、回避策を考えてもらいたいと思っています。私はJavaでZ80コアを実装しており、別のスレッドでjava.util.Timerオブジェクトを使って速度を落とそうとしています。Windows XPとWindows 7のJavaタイミングの精度
基本的なセットアップでは、実行ループを1つのスレッドで1秒間に50回実行しています。しかし、この実行ループ内では、多くのサイクルが実行され、wait()が呼び出されます。外部タイマースレッドは、P80 Sega Master Systemのクロック周波数3.54MHz(ish)をシミュレートして、Z80オブジェクトのnotifyAll()を20msごとに呼び出します。
上記の方法は、Windows 7(2台のマシンを試しました)では完全に動作しますが、2台のWindows XPマシンを試してみましたが、どちらもタイマーオブジェクトが約50%ほど遅くなっています。つまり、Windows XPマシンでは、1秒間のエミュレーション時間が実際には約1.5秒かかります。
私はTimerオブジェクトの代わりにThread.sleep()を使用しようとしましたが、これは全く同じ効果があります。私はほとんどのOSで1ミリ秒より良いとは言えないが、1000ミリ秒ではなく999ミリ秒または1001ミリ秒で時間を細分化できることを認識している。私が考えることができないことは1562msです - 私の方法は新しいバージョンのWindowsではうまくいくが、古いものではどうして理解できないのですか?私は割り込み期間などを調査しましたが、回避策を開発しました。
誰でもこの問題の原因と推奨される回避策を教えてください。どうもありがとう。
アップデート:ここでは、私は同じ問題を表示するために構築された小さなアプリケーションのための完全なコードです:
import java.util.Timer;
import java.util.TimerTask;
public class WorkThread extends Thread
{
private Timer timerThread;
private WakeUpTask timerTask;
public WorkThread()
{
timerThread = new Timer();
timerTask = new WakeUpTask(this);
}
public void run()
{
timerThread.schedule(timerTask, 0, 20);
while (true)
{
long startTime = System.nanoTime();
for (int i = 0; i < 50; i++)
{
int a = 1 + 1;
goToSleep();
}
long timeTaken = (System.nanoTime() - startTime)/1000000;
System.out.println("Time taken this loop: " + timeTaken + " milliseconds");
}
}
synchronized public void goToSleep()
{
try
{
wait();
}
catch (InterruptedException e)
{
System.exit(0);
}
}
synchronized public void wakeUp()
{
notifyAll();
}
private class WakeUpTask extends TimerTask
{
private WorkThread w;
public WakeUpTask(WorkThread t)
{
w = t;
}
public void run()
{
w.wakeUp();
}
}
}
すべての主要なクラスはありませんこれらのワーカースレッドの1つを作成して開始されます。 Windows 7では、このコードは約999ms〜1000msの時間を生成しますが、これはまったく問題ありません。 Windows XPで同じjarファイルを実行すると、約1562ms〜1566msの時間が発生します。これは、これをテストした2台の別のXPマシンにあります。彼らはすべてJava 6のアップデート27を実行しています。
タイマーが20ms(かなり小さな値)のためにスリープしているので、この問題が発生しています - すべての実行ループを1秒間待機してwait wait() notifyAll()サイクルでは正しい結果が得られます - 私がしようとしていることを見ている人は(50fpsでSega Master Systemをエミュレートします)、これは解決策ではないことがわかります。インタラクティブな応答時間は、50のうち49をスキップします。私が言うように、Win7はこれにうまく対応します。私のコードが大きすぎる:-(
興味深い質問です。この動作を示す自己完結型のコードスニペットを提供することは可能でしょうか? – NPE
もしあなたが好きなら私はあなたにタイマーのソースコードを与えることができますか?私はあなたに多くを与えたいと思いますが、Z80コアは非常に重くなっています;-) – PhilPotter1987
@aix * "自己完結型コードスニペット" *自己完結型コードは短いかもしれませんが、定義上、スニペット](http://en.wikipedia.org/wiki/Snippet_%28programming%29)。私は[SSCCE](http://pscode.org/sscce.html)を投稿することをお勧めします。 –