Я получил ScheduledExecutorService
для планирования задач в среде JEE. Некоторые из этих задач оставляют ресурсы открытыми, когда они прерываются с помощью ScheduledExecutorService.shutdownNow()
(например, открывают файлы с помощью сторонней библиотеки, такой как Lucene).
Я знаю, что поток не может остановить его выполнение сам по себе: необходимо использовать способ остановить поток, проверяя флаг прерывания и останавливая выполнение метода, и если поток является блоком (например, wait (), sleep () и т. д.) или при выполнении какой-либо операции ввода-вывода в прерываемом канале Thread.interrupt()
приведет к увеличению InterruptedException
. В обоих случаях должен быть выполнен блок finally.
Смотри: http://download.oracle.com/javase/1,5.0/docs/api/java/lang/Thread.html#interrupt%28%29.
Очевидно, я уже пытался высвободить ресурсы с очень хорошо реализованным блоком finally в классе Task, но в некоторых средах (например, CentOS) блок finally не выполняется, когда поток прерывается. И тогда я нашел эту очень классную заметку в официальной документации Java:
Примечание. Если JVM завершает работу во время выполнения кода try или catch,
тогда блок finally может не выполняться. Аналогично, если нить
выполнение кода try или catch прерывается или уничтожается, наконец
блок может не выполняться, даже если приложение в целом
продолжается.
Итак, мне нужна ссылка на все запланированные задачи, чтобы реализовать какой-то открытый метод в классах Задач, который вызывает освобождение ресурсов. Могу ли я получить эти ссылки на классы задач из ScheduledExecutorService
? Или у вас есть крутая идея, чтобы решить мою проблему лучше?
Первое решение: заверните!
Создайте класс Wrapper для ScheduledExecutorService
и добавьте свойство, подобное этому:
private IdentityHashMap<ScheduledFuture<?>, Runnable> taskList;
При этом мы можем получить доступ к любому объекту Runnable напрямую или с помощью ScheduledFuture
, связанного с ним. Для создания экземпляра оболочки я могу получить ScheduledExecutorService
из метода Executors.newScheduledThreadPool()
и передать его моей оболочке.
Другое решение: расширить его!
Расширьте ScheduledThreadPoolExecutor
, добавьте свойство IdentityHashMap и перезапишите все методы, которые планируют или отменяют задания, чтобы добавить / удалить ссылку из карты.
Проблема с обоими решениями?
Если вызывающий объект вашей оболочки или расширенного класса получает объект SchedulerFuture<?>
, отменить задание можно с помощью метода SchedulerFuture<?>.cancel()
, минуя вашу «капсулу». С помощью обертки вы можете избежать передачи ссылки SchedulerFuture<?>
вызывающей стороне, но с расширенным классом вы не сможете (если вы создадите свои собственные методы в расширенном классе, вы получите тот же результат, что и обертку, но в очень путаница).
Элегантное решение: ваш собственный планировщик! Спасибо Kaj за указание на него ...
- Расширьте
ScheduledThreadPoolExecutor
, чтобы перезаписать
decorateTask()
метод
- Украсьте
Runnable
одной реализацией
ScheduledFuture
интерфейс
- Реализация одного пользовательского
cancel()
метода, который на самом деле
отменяет поток, но также управляет объектом Runnable
для принудительного
ресурс освобождающий.
Проверьте мой блог пост для деталей и примеров кода !!!