Пожалуйста, посмотрите на раздел «Изменить» моего вопроса.
а, которая меня раздражает, такая же, какэтот билет, По сути, если вы измените часы ОС на дату в прошлом, все потоки, которые спали во время изменения, не будут активированы.
Приложение, которое я разрабатываю, предназначено для работы 24/24, и мы хотели бы иметь возможность изменять дату ОС, не останавливая ее (например, переключаться с летнего времени на зимнее время). На данный момент происходит то, что когда мы изменяем дату на прошлое, некоторые части приложения просто замирают. Я заметил это на нескольких машинах, в Windows XP и Linux 2.6.37, а также с недавней JVM (1.6.0.22).
Я пробовал много спящих примитивов Java, но все они имеют одинаковое поведение:
Thread.sleep (длинный)Thread.sleep (long, int)Object.wait (длинный)Object.wait (long, int)Thread.join (длинный)Thread.join (long, int)LockSupport.parkNanos (длинный)java.util.Timerjavax.swing.TimerТеперь у меня нет идеи обойти эту проблему. Я думаю, что я ничего не могу сделать, чтобы предотвратить замерзание спящих нитей. Но я хотел бы, по крайней мере, предупредить пользователя при обнаружении опасного изменения системных часов.
Я придумал поток мониторинга, который обнаруживает такие изменения:
Thread t = new Thread(new Runnable() {
@Override
public void run() {
long ms1 = System.currentTimeMillis();
long ms2;
while(true) {
ms2 = ms1;
ms1 = System.currentTimeMillis();
if (ms1 < ms2) {
warnUserOfPotentialFreeze();
}
Thread.yield();
}
}
});
t.setName("clock monitor");
t.setPriority(Thread.MIN_PRIORITY);
t.setDaemon(true);
t.start();
Проблема заключается в том, что это приводит к росту нагрузки на приложение с 2% до 15% в режиме ожидания.
У вас есть идея обойти исходную проблему, или вы можете придумать другой способ контролировать появление замораживания потоков?
редактироватьИнго предложил не трогать системные часы. Я согласен, что это вообще не нужно. Проблема в том, что мы не контролируем, что наши клиенты делают со своими компьютерами (мы планируем продать сотни копий).
Хуже того: одна из наших машин демонстрирует эту проблему без какого-либо ручного вмешательства. Я предполагаю, что ОС (Windows XP) регулярно синхронизирует свои часы с часами RTC, и это заставляет часы ОС возвращаться во времени естественным образом.
эпилогЯ узнал, что некоторые утверждения в моем вопросе были неправильными. На самом деле есть две отдельные причины, связанные с моей первоначальной проблемой. Теперь я могу точно сказать две вещи:
Только на моей машине (archlinux с ядром 2.6.37 с OpenJDK 64 бит 1.6.0_22),Thread.sleep
, Object.wait
, Thread.join
, LockSupport.parkNanos
имеют ту же проблему: они просыпаются только тогда, когда системные часы достигают «целевого» времени пробуждения. Тем не менее, простойsleep
в моей оболочке проблема не проявляется.
На всех машинах, которые я тестировал (включая мою),java.util.Timer
а такжеjava.swing.Timer
имеют ту же проблему (они блокируются, пока не будет достигнуто «целевое» время).
Итак, что я сделал, это то, что я заменил все JavaTimer
более простой реализацией. Это решает проблему для всех машин, кроме моей (я просто надеюсь, что моя машина - исключение, а не правило).