当单线程应用程序中的主线程抛出一个未捕获的异常时,因为控制台中会打印堆栈跟踪(也因为程序停止),所以您很可能注意到.但在多线程应用程序中,尤其是在作为服务器运行并且不与控制台相连的应用程序中,线程死亡可能成为不太引人注目的事件,这会导致局部系统失败,从而产生混乱的应用程序行为.
许多应用程序用线程来提供后台服务 — 处理来自事件队列的任务.从套接字读取命令或执行 ui 线程以外的长期任务.当由于抛出未捕获的 runtimeexception 或 error,或者只是停下来,等待阻塞的 i/o 操作(原本未预计到阻塞),从而引起这些线程之一死亡时,会发生什么呢? 【程序编程相关:xmlhttp 抓取网页内容2】
在 java theory and practice 十月份的专栏文章中,我们研究了线程池,并研究了编写得不正确的线程池会如何“泄漏”线程,直到最终丢失所有线程.大多数线程池实现通过捕获抛出的异常或重新启动死亡的线程来防止这一点,但线程泄漏的问题并不仅限于线程池 — 使用线程来为工作队列提供服务的服务器应用程序也可能具有这种问题.当服务器应用程序丢失了一个工作线程(worker thread)时,在较长时间内应用程序仍可能显得一切正常,这使得该问题的真实原因难以确定. 【推荐阅读:Symbian游戏编程入门 (一) Sy】
示例服务器应用程序 【扩展信息:一个操作注册表的类】
有时,譬如当线程执行由用户启动的长期任务(如拼写检查)时,用户会注意到任务没有进展,他们可能会异常终止操作或程序.但其它时间,后台线程执行“清理维护”任务 ,它们可能消失很长时间而不被察觉.
考虑这样一个假设的中间件服务器应用程序,它聚合来自各种输入源的消息,然后将它们提交到外部服务器应用程序,从外部应用程序接收响应并将响应路由回适当的输入源.对于每个输入源,都有一个以其自己的方式接受其输入消息的插件(通过扫描文件目录.等待套接字连接.轮询数据库表等).插件可以由第三方编写,即使它们是在服务器 jvm 上运行的.这个应用程序拥有(至少)两个内部工作队列 — 从插件处接收的正在等待被发送到服务器的消息(“出站消息”队列),以及从服务器接收的正在等待被传递到适当插件的响应(“入站响应”队列).通过调用插件对象上的服务例程 incomingresponse(),消息被路由到最初发出请求的插件.从插件接收消息后,就被排列到出站消息队列中.由一个或多个从队列读取消息的线程处理出站消息队列中的消息.记录其来源并将它提交给远程服务器应用程序(假定通过 web 服务接口).... 下一页