Die Grundeinstellung besteht darin, dass ich einen Thread habe, der 50 Mal pro Sekunde eine Ausführungsschleife ausführt. Innerhalb dieser Ausführungsschleife werden jedoch viele Zyklen ausgeführt und dann wird wait() aufgerufen. Der externe Timer-Thread ruft alle 20 ms notifyAll() für das Z80-Objekt auf und simuliert so eine PAL-Sega-Master-System-Taktfrequenz von 3,54 MHz (ish).
Die oben beschriebene Methode funktioniert perfekt unter Windows 7 (habe zwei Rechner ausprobiert), aber ich habe auch zwei Windows XP-Rechner ausprobiert und auf beiden scheint das Timer-Objekt um etwa 50 % zu schlafen. Das bedeutet, dass eine Sekunde Emulationszeit auf einem Windows XP-Rechner tatsächlich etwa 1,5 Sekunden dauert.
Ich habe versucht, Thread.sleep() anstelle eines Timer-Objekts zu verwenden, aber das hat genau den gleichen Effekt. Mir ist klar, dass die Granularität der Zeit in den meisten Betriebssystemen nicht besser als 1 ms ist, aber ich kann mich mit 999 ms oder 1001 ms statt 1000 ms zufrieden geben. Was ich nicht ertragen kann, sind 1562 ms – ich verstehe einfach nicht, warum meine Methode auf neueren Windows-Versionen einwandfrei funktioniert, aber nicht auf der älteren. Vielen Dank.
Update: Hier ist der vollständige Code für eine kleinere App, die ich erstellt habe, um das gleiche Problem zu zeigen:
Code: Select all
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();
}
}
}
Ich finde, dass dieses Problem auftritt, weil der Timer 20 ms lang schläft (ziemlich kleiner Wert) – wenn ich alle Ausführungsschleifen für eine einzelne Sekunde in den Zyklus „wait wait() – notifyAll()“ stopfe, erzeugt dies das korrekte Ergebnis – ich bin sicher, dass Leute, die sehen, was ich versuche (ein Sega-Master-System mit 50 fps zu emulieren), erkennen werden, dass dies keine Lösung ist – Es gibt keine interaktive Antwortzeit und überspringt 49 von 50. Wie gesagt, Win7 kommt damit gut zurecht. Tut mir leid, wenn mein Code zu groß ist
Mobile version