Tengo un extraño problema - Estoy esperando que alguien me puede explicar lo que está sucediendo y una posible solución. Estoy implementando un núcleo Z80 en Java, y estoy intentando ralentizarlo, usando un objeto java.util.Timer en un hilo separado.Java precisión temporal en Windows XP vs Windows 7
La configuración básica es que tengo un hilo ejecuta un bucle ejecutar, 50 veces por segundo. Dentro de este bucle de ejecución, se ejecutan muchos ciclos y luego se invoca wait(). El subproceso externo del temporizador invocará notifyAll() en el objeto Z80 cada 20 ms, simulando una frecuencia de reloj del sistema PAL Sega Master de 3,54 MHz (ish).
El método que he descrito anteriormente funciona perfectamente en Windows 7 (probamos dos máquinas) pero también me han tratado dos equipos con Windows XP y en dos de ellos, el objeto Timer exceso de sueño parece estar en torno al 50% o menos. Esto significa que un segundo del tiempo de emulación realmente demora alrededor de 1,5 segundos más o menos en una máquina con Windows XP.
He intentado usar Thread.sleep() en lugar de un objeto Timer, pero esto tiene exactamente el mismo efecto. Me doy cuenta de que la granularidad del tiempo en la mayoría de los sistemas operativos no es mejor que 1 ms, pero puedo soportar 999 ms o 1001 ms en lugar de 1000 ms. Lo que no puedo aguantar es 1562ms - Simplemente no entiendo por qué mi método funciona bien en la versión más nueva de Windows, pero no en la anterior - He investigado los periodos de interrupción y demás, pero no parezco han desarrollado una solución alternativa.
Podría alguien por favor dígame la causa de este problema y una solución sugerida? Muchas gracias.
Actualización: Aquí está el código completo para una aplicación más pequeña he construido para mostrar el mismo problema:
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();
}
}
}
Toda la clase principal que hace es crear e iniciar uno de estos subprocesos de trabajo. En Windows 7, este código produce un tiempo de alrededor de 999ms - 1000ms, que es totalmente correcto. Sin embargo, ejecutar el mismo jar en Windows XP produce un tiempo de alrededor de 1562 ms - 1566 ms, y esto es en dos máquinas separadas de XP que he probado esto. Todos están ejecutando Java 6 actualización 27.
Me parece que este problema está sucediendo porque el temporizador está durmiendo durante 20ms (un valor bastante pequeño) - si bung todos los bucles de ejecución por un solo segundo en esperar esperar() - notifyAll() ciclo, esto produce el resultado correcto - estoy seguro de que las personas que ven lo que estoy tratando de hacer (emulan un Sega Master System a 50 fps) verán que esto no es una solución, sin embargo, no dará un resultado. tiempo de respuesta interactivo, omitiendo 49 de cada 50. Como ya he dicho, Win7 se adapta bien a esto. Lo siento si mi código es demasiado grande :-(
Interesante pregunta. ¿Sería posible para usted proporcionar un fragmento de código autónomo que muestre este comportamiento? – NPE
¿Puedo darle el código fuente del temporizador si lo desea? Te doy la suerte, pero el núcleo del Z80 se perfila como bastante robusto ;-) – PhilPotter1987
@aix * "fragmento de código autónomo" * El código autónomo puede ser corto, pero no puede (por definición) ser un [ snippet] (http://en.wikipedia.org/wiki/Snippet_%28programming%29). Recomiendo publicar un [SSCCE] (http://pscode.org/sscce.html). –