Точный сон для Java на Windows - PullRequest
21 голосов
/ 05 мая 2009

Кто-нибудь знает библиотеку, которая предоставляет Thread.sleep () для Java с ошибкой не более 1-2 миллисекунд?

Я пробовал смесь Sleep, измерения ошибок и BusyWait, но я не могу получить такую ​​надежность на разных компьютерах с Windows.

Это может быть собственная реализация, если реализация доступна также для Linux и MacOS.

EDIT Ссылка, предоставленная Ником (http://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks), является действительно хорошим ресурсом для понимания проблем, возникающих во всех типах таймеров / снов / тактов Java.

Ответы [ 9 ]

17 голосов
/ 05 мая 2009

Для улучшения детализации сна вы можете попробовать следующее на этой странице Thread.sleep .

Ошибки с Thread.sleep () под Windows

Если время имеет решающее значение для вашего приложение, то неэлегантный, но практический способ обойти эти ошибки это оставить работающий поток демона на протяжении всего вашего приложение, которое просто спит для большое простое число миллисекунд (Long.MAX_VALUE будет делать). Сюда, период прерывания будет установлен один раз за вызов вашего приложения, минимизировать влияние на систему часы и установка сна зернистость до 1 мс даже там, где период прерывания по умолчанию не 15 мс.

На странице также упоминается, что она вызывает общесистемное изменение Windows, что может привести к быстрому запуску часов пользователя из-за этой ошибки .

EDIT

Более подробная информация об этом доступна здесь и связанный отчет об ошибке от Sun.

11 голосов
/ 28 октября 2009

Это примерно на 5 месяцев позже, но может быть полезно для людей, читающих этот вопрос. Я обнаружил, что java.util.concurrent.locks.LockSupport.parkNanos() делает то же самое, что и Thread.sleep(), но с точностью до наносекунды (в теории) и гораздо лучше, чем Thread.sleep() на практике. Конечно, это зависит от используемой среды выполнения Java, поэтому YMMV.

Посмотрите: LockSupport.parkNanos

(я подтвердил это на виртуальной машине Sun 1.6.0_16-b01 для Linux)

8 голосов
/ 07 июня 2010

К сожалению, в Java 6 все связанные с java методы сна в ОС Windows [включая LockSupport.awaitNanos ()] основаны на миллисекундах, как упоминалось несколькими людьми выше.

Одним из способов подсчета точного интервала является «спин-доходность». Метод System.nanoTime () выдает довольно точный счетчик относительного времени. Стоимость этого звонка зависит от вашего оборудования и лежит где-то 2000-50 нано.

Здесь предлагается альтернатива Thread.sleep ():

   public static void sleepNanos (long nanoDuration) throws InterruptedException {
        final long end = System.nanoTime() + nanoDuration;
        long timeLeft = nanoDuration;
        do {
            if (timeLeft > SLEEP_PRECISION)
                Thread.sleep (1);
            else
                if (timeLeft > SPIN_YIELD_PRECISION)
                    Thread.yield();

            timeLeft = end - System.nanoTime();
        } while (timeLeft > 0);
    }

У этого подхода есть один недостаток - в течение последних 2-3 миллисекунд ожидания ядро ​​процессора поражает. Обратите внимание, что sleep () / yield () поделится с другими потоками / процессами. Если вы готовы немного пойти на компромисс с процессором, это дает вам очень точный сон .

4 голосов
/ 05 мая 2009

JDK предлагает класс Timer.

http://java.sun.com/j2se/1.5.0/docs/api/java/util/Timer.html

Чтение документации ясно указывает на то, что, помимо сантехники, чтобы сделать это обобщенной структурой, она не использует ничего более сложного, чем вызов Object.wait (timeout):

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#wait(long)

Итак, вы, вероятно, можете прекратить погоню, просто воспользовавшись Object #, подождите сами.

Помимо этих соображений, факт остается фактом, что JVM не может гарантировать точность времени на разных платформах. (Прочитайте документы на http://java.sun.com/j2se/1.5.0/docs/api/java/lang/System.html#currentTimeMillis())

Я думаю, вам нужно будет поэкспериментировать с компромиссным решением, сочетающим таймер и опрос занятости, если вы хотите добиться максимальной точности синхронизации на вашей платформе. Фактически объект # wait (1) -> System # nanoTime -> вычисление дельты -> [цикл при необходимости].

Если вы готовы развернуть свой собственный, JNI в значительной степени оставляет его открытым для решений для конкретных платформ. Я блаженно не осведомлен о внутренностях Windows, но, очевидно, если хост-операционная система действительно обеспечивает достаточно точные службы таймера в реальном времени, базовая структура настройки собственной библиотеки timerRequest (timedelta, callback) не должна быть недосягаемой.

4 голосов
/ 05 мая 2009

Нет веских причин использовать Thread.sleep() в обычном коде - это (почти) всегда признак плохого дизайна. Наиболее важным является то, что нет гарантии, что поток продолжит выполнение после указанного времени, потому что семантика Thread.sleep() заключается просто в том, чтобы просто остановить выполнение на определенное время, но не продолжать сразу после того, как этот период истек.

Итак, хотя я не знаю, чего вы пытаетесь достичь, я вполне уверен, что вы должны использовать вместо этого таймер.

3 голосов
/ 15 мая 2009

Хак Long.MAX_VALUE - это рабочее решение.

Я попытался Object.wait (int milis) заменить Thread.sleep, но обнаружил, что Object.wait так же точен, как Thread.sleep (10 мс под Windows). Без взлома оба метода не подходят для любой анимации

1 голос
/ 05 мая 2009

Вы можете попробовать использовать новые библиотеки параллелизма. Что-то вроде:

private static final BlockingQueue SLEEPER = new ArrayBlockingQueue(1);
public static void main(String... args) throws InterruptedException {
    for(int i=0;i<100;i++) {
        long start = System.nanoTime();
        SLEEPER.poll(2, TimeUnit.MILLISECONDS);
        long time = System.nanoTime() - start;
        System.out.printf("Sleep %5.1f%n", time/1e6);
    }
}

Это спит от 2,6 до 2,8 миллисекунд.

1 голос
/ 05 мая 2009

Используйте одно из Thread::join переопределений в текущем потоке. Вы указываете количество миллисекунд (и наносекунд) ожидания.

0 голосов
/ 05 мая 2009

Похоже, вам нужна реализация реального времени Java .

...