Я отправляю вызываемые
объекты в ThreadPoolExecutor
, и они, похоже, прилипают
Глядя на дамп кучи с помощью инструмента MAT для Eclipse, можно увидеть, что на Callable
объекты ссылаются вызываемые FutureTask $ Sync
вызываемые переменная. На 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 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 собирает мусор и не утекает навсегда?