Точность синхронизации Java в Windows XP и Windows 7JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Точность синхронизации Java в Windows XP и Windows 7

Сообщение Anonymous »

У меня странная проблема. Я надеюсь, что кто-нибудь сможет объяснить мне, что происходит, и возможное решение. Я реализую ядро ​​Z80 на Java и пытаюсь замедлить его, используя объект java.util.Timer в отдельном потоке.

Базовая настройка заключается в том, что у меня есть один поток, выполняющий цикл выполнения 50 раз в секунду. В этом цикле выполнения выполняется много циклов, а затем вызывается функция wait(). Внешний поток Timer будет вызывать notifyAll() для объекта Z80 каждые 20 мс, имитируя тактовую частоту PAL Sega Master System 3,54 МГц (около).

Метод, который я описал выше, отлично работает в Windows 7 (пробовал две машины), но я также пробовал две машины с Windows XP, и на обеих из них объект Timer, похоже, загружается примерно на 50 % или около того. Это означает, что одна секунда эмуляции на компьютере с Windows XP на самом деле занимает около 1,5 секунды или около того.

Я пробовал использовать Thread.sleep() вместо объекта Timer, но это дает точно такой же эффект. Я понимаю, что детализация времени в большинстве ОС не лучше 1 мс, но я могу смириться с 999 мс или 1001 мс вместо 1000 мс. С чем я не могу мириться, так это с 1562 мс - я просто не понимаю, почему мой метод работает нормально в более новой версии 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();
}
}
}
Все, что делает основной класс, — это создает и запускает один из этих рабочих потоков. В Windows 7 этот код выдает время около 999–1000 мс, что вполне нормально. Однако запуск того же jar-файла в Windows XP дает время около 1562–1566 мс, и это на двух отдельных машинах с XP, которые я тестировал. Все они используют обновление Java 6 версии 27.

Я обнаружил, что эта проблема возникает из-за того, что таймер спит в течение 20 мс (довольно небольшое значение) - если я включаю все циклы выполнения на одну секунду в цикл wait wait() - notifyAll(), это дает правильный результат - я уверен, что люди, которые видят, что я пытаюсь сделать (эмулировать Sega Master System со скоростью 50 кадров в секунду), увидят, что это не решение - хотя - интерактивного времени ответа он не даст, пропуская 49 из каждых 50. Как я уже сказал, Win7 с этим прекрасно справляется. Извините, если мой код слишком велик :-(

Подробнее здесь: https://stackoverflow.com/questions/755 ... -windows-7
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»