Подтвердить что ты не робот

Выйдите из потока при загрузке приложения

Я поддерживаю библиотеку, которая запускает поток демона для работы в фоновом режиме. В обычных приложениях Java и Android этот поток запускается один раз и выполняется на протяжении всего процесса. Он никогда не выходит и все в порядке.

Когда моя библиотека включена в контейнер приложения, который поддерживает разгрузку приложения (например, Tomcat), приложение никогда не выгружается. Мой бегущий поток содержит сильные ссылки на собственный класс и предотвращает разгрузку всего приложения. Пользователи моей библиотеки не могут "горячей" заменой своего приложения, не теряя памяти каждый раз.

Какой лучший способ получить сигнал, когда контейнер приложения хочет выгрузить мою библиотеку?

Это небольшая библиотека, не зависящая от API-интерфейсов контейнера приложений. Он не знает, в какой контейнер приложения он работает, и он не хочет!

Тот факт, что эта библиотека запускает поток, является деталью реализации. Конечным пользователям библиотеки не нужно знать, что поток запускается, и это не их ответственность, чтобы закрыть его.

4b9b3361

Ответ 1

Не можете ли вы определить, была ли ваша библиотека использована приложением за последние x минут/секунд и отключить поток, если нет? Перезапустить его при следующем использовании? java.util.concurrent.ThreadPoolExecutor работает таким образом.

Ответ 2

Лучше всего обеспечить метод очистки библиотеки. Конечный пользователь должен будет вызвать его (предположительно, исходя из использования жизненного цикла приложения в контейнере). Вы также можете предоставить Listener для тех случаев, когда он используется в совместимом контейнере сервлетов (например, Tomcat), но ваш конечный пользователь все равно должен знать и помещать дескриптор в web.xml.

Единственная альтернатива заключается в том, что ваш конечный пользователь должен будет создать Listener, которому удастся заставить поток умереть. Мне приходилось делать это несколько раз, и это некрасиво. Обычно это связано с использованием рефлексии, чтобы избавиться от нити и убить ее. Конечно, исключение ThreadDeath обрабатывается некоторыми библиотеками, и потоки отказываются умирать. Это требует более значительного использования рефлексии для устранения беспорядка.

Вашим конечным пользователям намного лучше, если вы дадите им простой способ очистки библиотеки. Это отстой, что они должны знать о ваших деталях реализации, но они уже делают это, потому что вы сохраняете приложение при разгрузке.

Ответ 3

Это интересная проблема. Одна из идей, которую вы можете попробовать:

Попросите поток демона использовать слабые ссылки на вашу библиотеку. Затем у вас есть какой-то защитный объект в библиотеке, если метод finalize() уничтожит поток демона.

Будет ли что-то подобное работать?

Ответ 4

Вы можете использовать ComponentCallbacks2.onTrimMemory(). Это вызывается, когда система неактивна для ресурсов, а приложение в фоновом режиме должно освобождать ресурсы.

Мой опыт в том, что когда вызывается onTrimMemory (TRIM_MEMORY_COMPLETE), приложение вот-вот должно быть убито.