Есть ли способы припарковать поток на основе автономных часов, не зависящих от системных часов?

Чтобы текущий поток оставался на заданное время ожидания, я могу использовать:

LockSupport.parkNanos(long nanos);

or

Thread.sleep(long millis);//internally same as Object.wait(long) i guess.

К сожалению, все внутренние тики этих двух методов основаны на системных часах.

Если системные часы изменяются (с помощью ntptime или вручную) во время периода ожидания, этот метод не будет действовать должным образом.

например, в t0 я вызываю этот метод, например Thread.sleep (dt), чтобы засыпать dt секунд. Во время периода ожидания я устанавливаю свои системные часы на 20 секунд вперед, затем поток будет спать фактически dt + 20 секунд.

используйте следующий код, чтобы проверить это:

         public static void main(String[] args) throws InterruptedException {  
long s = System.nanoTime();  
int _10sec = 10 * 1000;  
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(_10sec));  
//or Thread.sleep(_10sec);
long e = System.nanoTime();  
long used = e - s;  
System.out.println("Used:" + TimeUnit.NANOSECONDS.toMillis(used)); }

используйте что-то вроде «date && sudo date -s 16:10:40», чтобы установить системные часы вперед на несколько минут во время ожидания, и вы увидите, что произошло на выходе.

Это печально, потому что в моем продукте многие вещи основаны на системных часах,

например, Scheduler (вызывающий наконец LockSupport.park) для проверки пульса через соединение Socket.

Если системные часы были переведены вперед дольше, чем время ожидания, планировщик посчитает, что время ожидания истекло, но на самом деле это не так.

Кто-нибудь сталкивался с такой же проблемой, и как ее решить?

ИЗМЕНИТЬ:

В моем продукте высокой доступности я использую Watchdog, чтобы убить ОС, когда большая нагрузка блокирует систему (так называемая стратегия самоубийства). Я должен кормить собаку изнутри, чтобы предотвратить нежелательное самоубийство , Использование ThreadSupport.parkNanos (xxx) приведет к неожиданному самоубийству


person BlackJoker    schedule 11.04.2013    source источник
comment
Вам нужен интерфейс Java для функции POSIX clock_nanosleep? AFAIK Java вообще не поддерживает монотонные часы.   -  person nosid    schedule 11.04.2013
comment
@ nosid, да, я думаю, что эта проблема не может быть решена в java, поэтому я ищу кое-какие рабочие места, чтобы минимизировать эффект.   -  person BlackJoker    schedule 12.04.2013


Ответы (2)


Я бы периодически просыпался во сне, например. каждую секунду, 5 секунд или минуту. Он может проверить currentTimeMillis (), если вам нужно скорректированное время, или nanoTime (), если вам нужно монотонно увеличивающееся время.

person Peter Lawrey    schedule 11.04.2013
comment
Я рассмотрю возможность использования своего продукта, в любом случае спасибо. - person BlackJoker; 11.04.2013
comment
Пробуждение каждую секунду имеет очень небольшие накладные расходы, если у вас нет большого количества потоков (в этом случае я предлагаю вам иметь меньше потоков). ЦП может обрабатывать более 10 миллиардов инструкций в секунду, и для компьютера это вечность. - person Peter Lawrey; 11.04.2013
comment
Да, так что, возможно, я смогу разработать основу для планировщика на этом, разделить долгую задержку на части, использовать nanoTime (), но может потерять некоторую точность - person BlackJoker; 11.04.2013
comment
График в лучшем случае точен только примерно до 1 мс, и я видел задержки в 40 мс на загруженной машине. т.е. он просыпается с опозданием на 40 мс. Поскольку у вас нет системы реального времени, вы в любом случае должны предполагать, что она слишком точна. - person Peter Lawrey; 11.04.2013
comment
учтите это: я хочу спать 10 секунд, разделить на 1 секунду 10 раз, если, когда время составляет 500 мс, установить часы вперед на 100 секунд, тогда этот сон будет просыпаться через 100 с + 500 мс позже, что не решает проблему - person BlackJoker; 11.04.2013
comment
Проблема, как вы ее заявляете, не может быть решена. Задачу можно выполнить в прошлом. - person Peter Lawrey; 11.04.2013

Наконец Я использовал JNI в Linux для решения этой проблемы. В области Java действительно нет выхода

#include <jni.h>
#include <unistd.h>
#include <LinuxSleeper.h>


JNIEXPORT jint JNICALL Java_com_my_pkg_name_sleep_LinuxSleeper_sleep0
  (JNIEnv *env, jobject thisObj, jint secs){
    if( secs >= 0 ){
        return sleep(secs);
    }else{
        return 0;
    }
}

а класс java выглядит так:

public class LinuxSleeper extends CommonSleeper implements Sleeper {

    static {
        NativeUtils.loadLibrary("LinuxSleeper");
    }
@Override
    public int sleep(int seconds) {
     ///....
    }
    private native int sleep0(int seconds);
    }
person BlackJoker    schedule 08.07.2014