У меня есть несколько Callables, которые запрашивают некоторые JMX Beans, поэтому каждый может отключиться. Я хочу, чтобы опрос за значения позволяет говорить каждую секунду. Самый наивный подход - начать каждый в отдельном потоке, но я хочу свести к минимуму количество потоков. Какие варианты мне нужно сделать лучше?Каков наилучший подход к расписанию Callables, который может тайм-аут в ситуации опроса?
ответ
Мое толкование заключается в том, что у вас есть куча вызываемых объектов, которые необходимо опрашивать с некоторым интервалом. Проблема, связанная с пулом потоков, заключается в том, что пул будет загрязнен самыми медленными членами, а ваши более быстрые из них будут голодать.
Похоже, что у вас есть контроль над планированием, поэтому вы можете рассмотреть возможность экспоненциального отсрочки. То есть, после того, как Callable X запустится (и, возможно, тайм-аут), вы подождите 2 секунды вместо 1 секунды, прежде чем перепланировать его. Если он по-прежнему не работает, перейдите к 4s, затем 8s и т. Д. Если вы используете ScheduledThreadPoolExecutor, он поставляется со встроенным способом для этого, позволяя вам запланировать выполнение после установленной задержки.
Если вы установили постоянный таймаут, эта стратегия уменьшит восприимчивость вашего пула к монополизации медленными. Очень сложно полностью избавиться от этой проблемы. Использование отдельного потока на каждый запрашиваемый объект - действительно единственный способ убедиться, что вы не получаете голода, и это может быть очень ресурсоемким, как вы говорите.
Другой стратегией является ведение вашего пула в быстрый и медленный. Если объект отключен (например, более N раз), вы перемещаете его в медленный пул. Это ускоряет ваш быстрый пул, и хотя медленные все проникают друг в друга, по крайней мере, они не забивают быстрый бассейн. Если у них есть хорошая статистика на некоторое время, вы можете снова отправить их в быстрый пул.
Как только вы окажетесь submit
a Callable
, вы получите Future
- ручку в будущее. Вы можете решить, ждать его завершения в течение определенного времени:
Future<String> future = executorService.submit(callable);
try {
future.get(1, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
} catch ...
Вызов получить с тайм-аут позволяет получить исключение, если задача не была завершена. Это не отличает не начатые задачи и не запускается, но не завершается. С другой стороны, cancel
будет принимать логический параметр mayStopIfRunning
, чтобы вы могли выбрать, например. только отменять запланированные задачи.
я согласен с robbotic ... реализации «» cachedThreadPool решит вашу проблему, как это будет ограничивать число потоков до оптимального уровня, в то же время имеет таймаут, который освободит ваши не-использовать ресурсы