Подтвердить что ты не робот

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

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

Например, если я хочу, чтобы поток приостанавливался на 100 наносекунд, и я вызываю Thread.sleep(0, 100). Вся стоимость этого процесса invocation_cost + 100 наносекунд, что может быть намного больше того, что я хочу. Как я мог избежать этой проблемы и достичь своей цели?

Причина, по которой мне нужно, это то, что я хочу сделать симуляцию офлайн. Я профилировал время выполнения задачи; Теперь я хочу имитировать это время выполнения, приостановив поток за тот же период времени.

Спасибо!

4b9b3361

Ответ 1

Гранулярность сна обычно связана периодом прерывания планировщика потока. В Linux этот период прерывания обычно равен 1 мс в последних ядрах. В Windows период прерывания планировщика обычно составляет около 10 или 15 миллисекунд

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

EDIT. Я подозреваю, что вы получите лучшие результаты на jrockit + solaris. Цифры в окне окна ужасны.

@Test
public void testWait(){
    final long INTERVAL = 100;
    long start = System.nanoTime();
    long end=0;
    do{
        end = System.nanoTime();
    }while(start + INTERVAL >= end);
    System.out.println(end - start);
}

Ответ 2

Для моделирования я бы не пытался имитировать в реальном времени, поскольку это не дает вам воспроизводимых результатов. т.е. вы не можете проверить свое симуляцию.

Вместо этого я бы использовал управляемые данными, имитированные часы и запускал все как можно быстрее. Это дает вам воспроизводимые результаты и позволяет вам имитировать быстрее, чем в реальном времени (например, от 2x до 100 раз быстрее).


Подозревая нить занимает около 10 микросекунд. Нет смысла пытаться приостановить поток за меньшее время, чем это.

Ожидание в течение короткого периода времени вы можете попробовать.

long start = System.nanotime();
while(start + delay >= System.nanoTime());

Примечание: как комментарий @EugeneBeresovsky, после того, как ваша машина работает в течение 292 лет, это может переполняться, поэтому вы можете написать это как

while(System.nanoTime() - start < delay);

Это будет штрафовать за задержки менее 292 лет вместо этого. Вы можете использовать System.currentTimeMillis() для гораздо более длительных задержек.

Однако даже это ненадежно, так как System.nanoTime() может принимать до 300 нс на Centos 5.x, поэтому вызов его дважды займет гораздо больше 100 нс. Также многие ОС имеют разрешение 1000 нс (1 микросекунда), поэтому этот цикл будет ждать до 1 микросекунды, независимо от задержки, которую вы ищете.

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

За задержку в 100 нс я подозреваю, что было бы лучше заняться ожиданием того, чего вы ожидаете, вместо создания отдельного цикла занятости.

Ответ 3

public static void busySleep(long nanos)
{
  long elapsed;
  final long startTime = System.nanoTime();
  do {
    elapsed = System.nanoTime() - startTime;
  } while (elapsed < nanos);
}

Ответ 4

Еще одна проблема с Thread.sleep() заключается в том, что она не гарантируется для пробуждения по истечении указанного времени. Спящая нить гарантируется для сна за указанные нано/микросекунды, но не должна быть активирована для пробуждения сразу после этого. Поскольку вы говорите о промежутках между наносекундами, вы можете попробовать Object.wait(long, int).

Я был вполне согласен с порядком в 10 с наносекунд с указанным выше методом.

Ответ 5

Ожидайте ожидание (т.е. цикл цикла while через столько чисел ничего не делает). В начале вашей программы вы можете набрать время, затраченное на выполнение этого оживленного ожидания, и увеличить или уменьшить его до 5 наносекунд.

Я обнаружил, что object.wait получает волосатое с этой частотой также замечает, что занятое решение ожидания, скорее всего, будет зависимым от машины. Следовательно, у вас должен быть шаг калибровки в начале вашей программы.