Пожалуйста, не отвечайте с опозданием на 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 по улучшению своей среды в качестве основы для приложений, требующих высокой точности синхронизации, таких как музыкальные программы и игры?

Спасибо всем за чтение моего длинного вопроса / статьи. Я надеюсь, что некоторые люди могут найти мое исследование полезным!

Ответы на вопрос(5)

Ваш ответ на вопрос