Я думаю, что это - общий сценарий для многопоточных JAVA-приложений, таким образом, я попытаюсь описать его здесь.
В моем Приложении Java у меня есть объект threadExecutor, который определяет Пул 5 Потоков.
ExecutorService threadExecutor = Executors.newFixedThreadPool(5);
sendCallables метод ответственен для присвоения Списка Заданий Исполнителю.
Я отслеживаю Список с ObjectX. Таким образом я могу сослаться назад на список фьючерсов, если Пользователь хочет прервать/отменить Потоки. Что-то вроде этого:
Map>> map = new HashMap>();
public void sendCallables(ObjectX referenceObj, List> list) {
...
List> futureList = new ArrayList>();
for(Callable myCallableJob : list) {
Future future = threadExecutor.submit(myCallableJob);
futureList.add(future);
}
...
map.add(referenceObj, futureList);
...
}
public void cancelFutures(ObjectX referenceObj) {
...
List> list = map.get(referenceObj);
for(Future future : list) {
future.cancel();
}
map.remove(referenceObj);
....
}
Пока все хорошо.
Теперь существуют случаи, когда нет никакой потребности больше выполнять отправленные задачи.
В этих ситуациях решение об отмене задач должно быть принято разумно/автоматически Приложением.
Примеры таких случаев могут быть найдены в веб-приложении, когда сессия Пользователя истекает или когда определенный Поток (связанный с отправленными задачами) концы перед всеми Заданиями выполняется.
Так в основном я должен буду назвать cancelFutures (referenceObj) каждый раз, что нет никакого смысла для моего приложения, чтобы продолжить выполнять Задания. Я должен определить каждую ситуацию, когда приложение должно назвать ее.
Я задаюсь вопросом, существует ли лучший подход, чтобы сделать это.
Я думал в WeakHashMap для сможения к очистке Карты, после того как на referenceObj больше не ссылается Приложение, но это не останавливает фьючерсы, которые будут выполняться, как я все еще должен назвать .cancel () на них (своего рода eventHandler, связанные с WeakHashMap, удаляют (Объектный) метод?)
Думаю, решение, которое вы предлагаете, довольно хорошее. Если вы действительно действительно хотите добиться отмены сборщика мусора для referenceObj, вы можете использовать комбинацию WeakReference и ReferenceQueue.
Объявите один из них в вашем вспомогательном классе выполнения.
ReferenceQueue<ObjectX> refQ = new ReferenceQueue<ObjectX>();
Делайте это каждый раз, когда отправляется пакет задач.
new WeakReference<ObjectX>( referenceObj, refQ ).enqueue();
Имейте поток, который просто запускает этот цикл, который извлекает объекты, которые стали слабо достижимыми (подходящими для GC), и отменяет фьючерсы / задачи.
while (true)
{
// this blocks
ObjectX referenceObj = refQ.remove().get();
cancelFutures( referenceObj );
}
Если я правильно понимаю вашу проблему, у вас происходят разные виды деятельности, и вы не хотите связывать эти действия вместе только потому, что их можно отменить.
Мне кажется, что каждый случай, требующий отмены, должен запускать событие. Слушатель событий будет прослушивать эти события и отменять соответствующее Future
.
Ваш пример о сеансах - у вас будет класс, который реализует javax.servlet.http.HttpSessionListner
, обнаруживает соответствующие задачи, которые необходимо отменить, и запускает событие для отмены этих задач. Поскольку все асинхронно, вам все равно, завершена ли отмененная задача или нет, поэтому ничего не теряется.