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

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

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

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

Я пробовал использовать 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 () - notifyAll (), это даст правильный результат - Я уверен, что люди, которые видят, что я пытаюсь сделать (имитировать систему Sega Master со скоростью 50 кадров в секунду), увидят, что это не решение, хотя оно не дает интерактивного времени отклика, пропуская 49 из 50. Как я уже сказал, Win7 с этим прекрасно справляется. Извините, если мой код слишком велик: - (

9
задан PhilPotter1987 26 September 2011 в 18:17
поделиться