Пожалуйста, не отвечайте с опозданием на 3-месячные посты, в основном с той же информацией, которая уже есть в теме! Или, по крайней мере, сделать это комментарий.
рограммировании анимации и маленьких игр я осознал невероятную важностьThread.sleep(n);
Я полагаюсь на этот метод, чтобы сообщить операционной системе, когда моему приложению не понадобится процессор, и с помощью этого позволяет моей программе работать с предсказуемой скоростью.
Моя проблема в том, что JRE использует разные методы реализации этой функциональности в разных операционных системах. В основанных на UNIX (или под влиянием) ОС: таких, как Ubuntu и OS X, базовая реализация JRE использует хорошо функционирующую и точную систему для распределения процессорного времени между различными приложениями, что делает мою 2D-игру гладкой и без задержек , Тем не менее, в Windows 7 и более старых системах Microsoft распределение времени процессора, кажется, работает по-другому, и вы обычно возвращаете время процессора после заданного количества сна, которое варьируется примерно через 1-2 мс от целевого сна. Тем не менее, вы получаете случайные всплески дополнительного 10-20 мс времени сна. Это заставляет мою игру задерживаться каждые несколько секунд, когда это происходит. Я заметил, что эта проблема существует в большинстве Java-игр, которые я пробовал на Windows, и Minecraft является заметным примером.
Теперь я искал в Интернете, чтобы найти решение этой проблемы. Я видел много людей, использующих толькоThread.yield();
вместоThread.sleep(n);
, который работает безупречно за счет того, что используемое в настоящее время ядро ЦП получает полную нагрузку, независимо от того, сколько ЦП фактически требует ваша игра. Это не идеально для игры на ноутбуках или рабочих станциях с высоким энергопотреблением, и это ненужный компромисс на компьютерах Mac и Linux.
Оглядываясь дальше, я нашел широко используемый метод исправления несоответствий во время сна, называемый «спин-сон», где вы заказываете сон только на 1 мс за раз и проверяете согласованность, используяSystem.nanoTime();
метод, который очень точен даже в системах Microsoft. Это помогает в течение 1-2 мс несогласованности сна, но не помогает против случайных всплесков + 10-20 мс несогласованности сна, поскольку это часто приводит к увеличению времени, затрачиваемого на то, чтобы один цикл моего цикла занял все все вместе.
После долгих поисков я нашел загадочную статью Энди Малакова, которая очень помогла улучшить мой цикл:http://andy-malakov.blogspot.com/2010/06/alternative-to-threadsleep.html
Основываясь на его статье, я написал этот метод сна:
// Variables for calculating optimal sleep time. In nanoseconds (1s = 10^-9ms).
private long timeBefore = 0L;
private long timeSleepEnd, timeLeft;
// The estimated game update rate.
private double timeUpdateRate;
// The time one game loop cycle should take in order to reach the max FPS.
private long timeLoop;
private void sleep() throws InterruptedException {
// Skip first game loop cycle.
if (timeBefore != 0L) {
// Calculate optimal game loop sleep time.
timeLeft = timeLoop - (System.nanoTime() - timeBefore);
// If all necessary calculations took LESS time than given by the sleepTimeBuffer. Max update rate was reached.
if (timeLeft > 0 && isUpdateRateLimited) {
// Determine when to stop sleeping.
timeSleepEnd = System.nanoTime() + timeLeft;
// Sleep, yield or keep the thread busy until there is not time left to sleep.
do {
if (timeLeft > SLEEP_PRECISION) {
Thread.sleep(1); // Sleep for approximately 1 millisecond.
}
else if (timeLeft > SPIN_YIELD_PRECISION) {
Thread.yield(); // Yield the thread.
}
if (Thread.interrupted()) {
throw new InterruptedException();
}
timeLeft = timeSleepEnd - System.nanoTime();
}
while (timeLeft > 0);
}
// Save the calculated update rate.
timeUpdateRate = 1000000000D / (double) (System.nanoTime() - timeBefore);
}
// Starting point for time measurement.
timeBefore = System.nanoTime();
}
SLEEP_PRECISION
Я обычно ставлю около 2 мс, иSPIN_YIELD_PRECISION
примерно до 10 000 нс для лучшей производительности на моем компьютере с Windows 7.
После тонны тяжелой работы это самое лучшее, что я могу придумать. Итак, так как я все еще беспокоюсь об улучшении точности этого метода сна, и я все еще не удовлетворен производительностью, я хотел бы обратиться ко всем вам, хакерам и аниматорам Java-игр, за предложениями по лучшему решению для Платформа Windows. Могу ли я использовать платформу для Windows, чтобы сделать ее лучше? Меня не волнует наличие небольшого кода, специфичного для платформы, в моих приложениях, поскольку большая часть кода не зависит от ОС.
Я также хотел бы знать, есть ли кто-нибудь, кто знает, что Microsoft и Oracle разрабатывают лучшую реализациюThread.sleep(n);
метод, или каковы дальнейшие планы Oracle по улучшению своей среды в качестве основы для приложений, требующих высокой точности синхронизации, таких как музыкальные программы и игры?
Спасибо всем за чтение моего длинного вопроса / статьи. Я надеюсь, что некоторые люди могут найти мое исследование полезным!