Вопрос по thread-sleep, scheduledexecutorservice, java, multithreading – Thread.sleep () VS Executor.scheduleWithFixedDelay ()

21

Цель: выполнять определенный код время от времени.

Вопрос: С точки зрения производительности, есть ли существенная разница между:

while(true) {
    execute();
    Thread.sleep(10 * 1000);
}

а также?

executor.scheduleWithFixedDelay(runnableWithoutSleep, 0, 10, TimeUnit.SECONDS);

Конечно, последний вариант более кошерный. Тем не менее, я хотел бы знать, должен ли я начать приключение под названием "Потратьте несколько дней на рефакторинг старого кода, чтобы попрощаться с Thread.sleep () ".

Обновление: этот код работает в среде супер / мега / гипер высокой нагрузки.

Я думаю, что оба одинаковы иscheduleWithFixedDelay инкапсулированный вызов сна. Subhrajyoti Majumder
Почему вы спрашиваете о производительностиспать операция? Dan
@Dan: Хорошо, что я вижу в дампе потока: java.lang.Thread.State: TIMED_WAITING (спит) VS java.lang.Thread.State: TIMED_WAITING (парковка). Там'Разница явно, возможно, тоже производительность. rudgirello
@Quoi: они неЭто действительно то же самое, что запланированный исполнитель может выполнять много запланированных задач и запускать их в меньшем количестве потоков, чем количество задач. Если вы просто используете сон, вы должны иметь поток для каждой задачи, которую выграфик". Steven Schlansker

Ваш Ответ

4   ответа
0

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

Вы можете создать пул потоков, используяScheduledThreadPoolExecutor сcorePoolSize больше 1. Затем, когда вы звонитеscheduleWithFixedDelay в том пуле потоков, если поток доступен, он будет использован повторно.

Это изменение может снизить загрузку ЦП, поскольку потоки повторно используются, а не уничтожаются и создаются, но степень сокращения будет зависеть от задач, которые они выполняют.выполняется, количество потоков в пуле и т. д. Использование памяти также будет снижаться, если некоторые задачи будут перекрываться, так как будет меньше потоков, которые бездействуют одновременно.

9

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

я бы предпочел последний стиль каждый раз, но если у вас есть первый и онэто будет стоить вам много, чтобы изменить его "улучшение производительности » ISN»Это особенно хорошее обоснование.

РЕДАКТИРОВАТЬ Re: 8000 потоков

8000 потоков - это очень много; Я мог бы перейти к запланированному исполнителю только для того, чтобы вы могли контролировать количество нагрузки на вашу систему. Вам нужно знать о вашем разном времени пробуждения, хотя я бы сказал, что больший риск - паническое бегство потоков, которые спят, а затем просыпаются в тесной последовательности и конкурируют за все системные ресурсы.

Я бы потратил время, чтобы бросить все это в фиксированный пул потоков, запланированный исполнителем. Одновременно должно работать только столько, сколько у вас доступно наиболее ограниченного ресурса (например, # core или # IO paths), плюс несколько, чтобы уловить любой помой. Это даст вам хорошую пропускную способность за счет задержки.

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

Если вам нужен более подробный совет, вы 'Возможно, мне придется описать, что выпытаемся сделать поподробнее.

Меня беспокоит то, что у нас есть 8000 потоков, и спящие потоки могут получить такой низкий приоритет, что они будут выполняться со значительной задержкой, что может привести к побочным проблемам с GC. rudgirello
1

Как я помню из исходного кода Java, главное отличие заключается в том, как все написано внутри.

ЗаSun Java 1.6 если вы используете второй подход, нативный код также вноситждать и уведомить звонки в систему. Таким образом, в некотором смысле более эффективный поток и процессор.

Но затем вы снова теряете контроль, и он становится более непредсказуемым для вашего кода - подумайте, что вы хотите спать 10 секунд.

Так что, если вы хотите большей предсказуемости - несомненно, вы можете выбрать вариант 1.

Кроме того, отметим, что в устаревших системах, когда вы сталкиваетесь с подобными вещами - 80% вероятности, что теперь есть лучшие способы сделать это, но магические числа существуют по причине (остальные 20%), поэтому измените их на собственный риск :)

2

Таймер создает очередь задач, которая постоянно обновляется. Когда таймер сделан, он не может быть мусором сразу. Таким образом, создание большего количества таймеров только добавляет больше объектов в кучу. Thread.sleep () только приостанавливает поток, поэтому объем памяти будет очень низкимTimer / TimerTask также учитывает время выполнения вашей задачи, поэтому оно будет немного более точным. И он лучше справляется с проблемами многопоточности (например, избегая взаимоблокировок и т. Д.).Если вы получите поток и получите исключение, то это проблема. Но TimerTask позаботится об этом. Он будет работать независимо от сбоя в предыдущем запускеПреимущество TimerTask заключается в том, что он намного лучше выражает ваши намерения (то есть читабельность кода), и в нем уже реализована функция cancel ().

Ссылка взята изВот

Похожие вопросы