Моя интерпретация заключается в том, что у вас есть куча вызываемых объектов, которые нужно опрашивать через некоторый интервал. Проблема, если вы используете пул потоков, состоит в том, что пул будет загрязнен самыми медленными членами, а ваши более быстрые будут голодать.
Похоже, у вас есть контроль над расписанием, так что вы можете рассмотреть экспоненциальный подход отсрочки. То есть после того, как Callable X запустился (и, возможно, по тайм-ауту), вы подождите 2 секунды вместо 1 секунды, прежде чем его перепланировать. Если это не помогло, перейдите к 4 с, затем к 8 и т. Д. Если вы используете ScheduledThreadPoolExecutor , он поставляется со встроенным способом сделать это, позволяя вам планировать свои исполнения после заданной задержки.
Если вы установите постоянное время ожидания, эта стратегия уменьшит восприимчивость вашего пула к монополизации медленными. Очень трудно полностью избавиться от этой проблемы. Использование отдельного потока для каждого запрашиваемого объекта - действительно единственный способ убедиться, что вы не получите голодание, и это может быть очень ресурсоемким, как вы говорите.
Другая стратегия состоит в том, чтобы объединить ваш пул в быстрый и медленный. Если у объекта истекает время (скажем, более чем в N раз), вы перемещаете его в медленный пул. Это позволяет быстро поддерживать ваш быстрый пул, и хотя медленные все мешают друг другу, по крайней мере они не забивают быстрый пул. Если они какое-то время имеют хорошую статистику, вы можете снова повысить их до быстрого пула.