Я отправляю Callable
объекты на ThreadPoolExecutor
, и они, похоже, торчат в памяти.
Глядя на дамп кучи с помощью инструмента MAT для Eclipse, можно увидеть, что Callable
объектына него ссылается переменная FutureTask$Sync
s callable .На FutureTask$Sync
ссылается переменная FutureTask
sync .На FutureTask
ссылается FutureTask$Sync
эта переменная $ 0 .
Я читал об этом ( здесь , здесь и на SO) и FutureTask
кажется, что вызываемый объект включен в ThreadPoolExecutor
submit () содержит ссылку на вызываемый объект навсегда.
Что меня смущает, так этокак гарантировать, что FutureTask
будет собирать мусор, чтобы он не продолжал удерживать вызываемое в памяти и хранить что-либо, что вызываемое может быть в памяти?
Просто чтобы подробнее рассказать о моей конкретной ситуацииЯ пытаюсь реализовать ThreadPoolExecutor
таким образом, чтобы при необходимости можно было отменить все представленные задачи.Я пробовал несколько различных методов, которые я нашел в SO и других местах, таких как полное выключение исполнителя (с помощью shutdown()
, shutdownNow()
и т. Д.), А также сохранение списка фьючерсов, возвращаемых на submit()
и вызов отмены для всех них.а затем очистить список фьючерсов.В идеале я хотел бы не выключать его, а просто cancel()
и очищать при необходимости.
Кажется, что все эти методы не имеют значения.Если я отправлю вызов в пул, есть большая вероятность, что он останется без дела.
Что я делаю не так?
Спасибо.
Редактировать:
По запросу, вот конструктор для ThreadPoolExecutor.
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
После дальнейшего тестирования я могу видеть, что если я позволю задачам, которые были переданы в ThreadPoolExecutorзакончить, то нет утечки.Если я попытаюсь отменить их в любом случае, например:
shutdownNow()
Или сохранить ссылку на будущее и вызвать отмену позже:
Future referenceToCancelLater = submit(task);
...
referenceToCancelLater.cancel(false);
Или, удалив их из очередис такими методами, как:
getQueue.drainTo(someList)
или
getQueue.clear()
или с циклическим просмотром сохраненных ссылок на фьючерсы и вызовом:
getQueue.remove(task)
Любой из этих случаев вызывает FutureTaskпридерживаться, как описано выше.
Итак, реальный вопрос во всем этом заключается в том, как правильно отменить или удалить элементы из ThreadPoolExecutor, чтобы FutureTask собирал мусор и не просачивался вечно?