我维护一个启动守护程序线程的库,以便在后台运行。在常规Java和Android应用程序中,此线程启动一次并在该进程的生命周期内运行。它永远不会退出,那没关系。
当我的库包含在支持应用程序卸载的应用程序容器(例如Tomcat)中时,应用程序永远不会卸载。我正在运行的线程拥有对其自己的类的强引用,并阻止整个应用程序被卸载。我的图书馆用户每次都不能热插拔应用程序而不会泄漏内存。
当应用程序容器希望卸载我的库时,发出信号的最佳方法是什么?
这是一个小型库,不依赖于应用程序容器API。它不知道它正在运行哪个应用程序容器而且它不想!
这个库启动一个线程的事实是一个实现细节。图书馆的最终用户不必知道线程正在被启动,关闭它是他们的责任。
答案 0 :(得分:7)
最好的办法是提供一种清理库的方法。最终用户必须调用它(可能是基于处理容器中的应用程序生命周期)。当在兼容的servlet容器(例如,Tomcat)中使用它时,您还可以为这些情况提供Listener
,但您的最终用户仍然必须知道并将描述符放在web.xml中。
唯一的另一种选择是你的最终用户必须创建一个能够让线程死掉的监听器。我不得不在几个场合这样做,这并不漂亮。它通常涉及使用反射来获取线程并将其杀死。当然,ThreadDeath异常由一些库处理,并且线程拒绝死亡。这需要更多地使用反射来清理混乱。
如果您给他们一个简单的清理库的方法,您的最终用户会好得多。它很糟糕,他们必须知道你的实现细节,但他们已经这样做了,因为你要保持应用程序不被卸载。
答案 1 :(得分:6)
无法确定应用程序是否在最后x分钟/秒内使用了lib,如果没有则关闭该线程?下次使用时重启吗? java.util.concurrent.ThreadPoolExecutor
以这种方式工作。
答案 2 :(得分:2)
这是一个有趣的问题。您可能想尝试一个想法:
让守护程序线程使用对库的弱引用。然后在库中有一些保护对象让它的finalize()
方法取下守护程序线程。
这样的事情会起作用吗?
答案 3 :(得分:1)
您可以使用ComponentCallbacks2.onTrimMemory()。当系统资源不足且后台应用程序释放资源时调用此方法。
我的经验是,当调用onTrimMemory(TRIM_MEMORY_COMPLETE)时,应用即将被杀死。