Thread.sleep() VS Executor.scheduleWithFixedDelay()
Цель: Выполнять определенный код каждый раз.
Вопрос: Что касается производительности, существует ли существенная разница между:
while(true) {
execute();
Thread.sleep(10 * 1000);
}
и
executor.scheduleWithFixedDelay(runnableWithoutSleep, 0, 10, TimeUnit.SECONDS);
?
Конечно, последний вариант более кошерный. Тем не менее, я хотел бы знать, должен ли я приступить к приключению под названием "Провести несколько дней рефакторинг устаревшего кода, чтобы попрощаться с Thread.sleep()".
Обновление:
Этот код работает в среде super/mega/hyper high-load.
Ответы
Ответ 1
Вы имеете дело со временем сна, называемым десятками секунд. Возможная экономия, изменяя ваш вариант сна здесь, вероятно, наносекунды или микросекунды.
Я бы предпочел последний стиль каждый раз, но если у вас есть первый, и вам будет стоить много, чтобы изменить его, "улучшение производительности" не является особенно хорошим оправданием.
EDIT re: 8000 потоков
8000 потоков - ужасно много; Я могу перейти к запланированному исполнителю, чтобы вы могли контролировать количество нагрузки, наложенной на вашу систему. Ваша точка зрения о разном времени пробуждения - это то, о чем нужно знать, хотя я бы сказал, что больший риск является падением нитей, спавших, а затем пробуждающихся в тесной последовательности и конкурирующих за все системные ресурсы.
Я потратил бы время, чтобы выбросить все это в фиксированный пул запланированных исполнителей. У вас будет столько одновременных одновременных действий, поскольку у вас есть доступ к самому ограниченному ресурсу (например, # ядрам или путям # IO), а также нескольким, чтобы забрать любую отставку. Это даст вам хорошую пропускную способность за счет латентности.
С помощью метода Thread.sleep()
будет очень сложно управлять тем, что происходит, и вы, вероятно, проиграете как пропускную способность, так и задержку.
Если вам нужен более подробный совет, вам, вероятно, придется описать, что вы пытаетесь сделать более подробно.
Ответ 2
Поскольку вы не упомянули версию Java, так что все может измениться.
Как я помню из исходного кода Java, основное отличие, которое приходит, - это то, как вещи написаны внутри.
Для Sun Java 1.6, если вы используете второй подход, собственный код также вызывает вызовы wait и notify в систему. Таким образом, в некотором смысле более эффективный поток и удобный для ЦП.
Но опять же вы теряете контроль, и он становится более непредсказуемым для вашего кода - считайте, что вы хотите спать в течение 10 секунд.
Итак, если вы хотите большей предсказуемости, вы можете пойти с опцией 1.
Кроме того, на стороне примечания, в унаследованных системах, когда вы сталкиваетесь с такими вещами - 80% шансов на то, что теперь есть лучшие способы сделать это, - но волшебные числа существуют по какой-либо причине (остальные 20%), изменить его на свой страх и риск:)
Ответ 3
Существуют разные сценарии,
- Таймер создает очередь задач, которые постоянно обновляются. Когда таймер будет выполнен, он может не быть собранным немедленно. Таким образом, создание большего количества таймеров добавляет больше объектов в кучу. Thread.sleep() только приостанавливает поток, поэтому накладные расходы памяти будут крайне низкими.
- Timer/TimerTask также учитывает время выполнения вашей задачи, поэтому он будет немного более точным. И он лучше справляется с проблемами многопоточности (например, избегая взаимоблокировок и т.д.).
- Если вы используете исключение и убиваете, это проблема. Но TimerTask позаботится об этом. Он будет работать независимо от отказа в предыдущем запуске
- Преимущество TimerTask заключается в том, что он значительно улучшает ваше намерение (то есть читаемость кода), и у него уже есть функция cancel().
Ссылка взята из здесь