Java理论与实践: 嗨,我的线程到哪里去了? - 编程入门网
Java理论与实践: 嗨,我的线程到哪里去了?时间:2010-12-21 IBM Brian Goetz当单线程应用程序中的主线程抛出一个未捕获的异常时,因为控制台中会打 印堆栈跟踪(也因为程序停止),所以您很可能注意到。但在多线程应用程序中 ,尤其是在作为服务器运行并且不与控制台相连的应用程序中,线程死亡可能成 为不太引人注目的事件,这会导致局部系统失败,从而产生混乱的应用程序行为 。 在 Java theory and practice十月份的专栏文章 中,我们研究了线程池, 并研究了编写得不正确的线程池会如何“泄漏”线程,直到最终丢失所有线程。 大多数线程池实现通过捕获抛出的异常或重新启动死亡的线程来防止这一点,但 线程泄漏的问题并不仅限于线程池 ― 使用线程来为工作队列提供服务的服务器 应用程序也可能具有这种问题。当服务器应用程序丢失了一个工作线程(worker thread)时,在较长时间内应用程序仍可能显得一切正常,这使得该问题的真实 原因难以确定。 许多应用程序用线程来提供后台服务 ― 处理来自事件队列的任务、从套接 字读取命令或执行 UI 线程以外的长期任务。当由于抛出未捕获的 RuntimeException 或 Error ,或者只是停下来,等待阻塞的 I/O 操作(原本 未预计到阻塞),从而引起这些线程之一死亡时,会发生什么呢? 有时,譬如当线程执行由用户启动的长期任务(如拼写检查)时,用户会注 意到任务没有进展,他们可能会异常终止操作或程序。但其它时间,后台线程执 行“清理维护”任务 ,它们可能消失很长时间而不被察觉。 示例服务器应用程序 考虑这样一个假设的中间件服务器应用程序,它聚合来自各种输入源的消息 ,然后将它们提交到外部服务器应用程序,从外部应用程序接收响应并将响应路 由回适当的输入源。对于每个输入源,都有一个以其自己的方式接受其输入消息 的插件(通过扫描文件目录、等待套接字连接、轮询数据库表等)。插件可以由 第三方编写,即使它们是在服务器 JVM 上运行的。这个应用程序拥有(至少) 两个内部工作队列 ― 从插件处接收的正在等待被发送到服务器的消息(“出站 消息”队列),以及从服务器接收的正在等待被传递到适当插件的响应(“入站 响应”队列)。通过调用插件对象上的服务例程 incomingResponse() ,消息被 路由到最初发出请求的插件。 从插件接收消息后,就被排列到出站消息队列中。由一个或多个从队列读取 消息的线程处理出站消息队列中的消息、记录其来源并将它提交给远程服务器应 用程序(假定通过 Web 服务接口)。远程应用程序最终通过 Web 服务接口返回 响应,然后我们的服务器将接收的响应排列到入站响应队列中。一个或多个响应 线程从入站响应队列读取消息并将其路由到适当的插件,从而完成往返“旅程” 。 在这个应用程序中,有两个消息队列,分别用于出站请求和入站响应,不同 的插件内可能也有另外的队列。我们还有几种服务线程,一个从出站消息队列读 取请求并将其提交给外部服务器,一个从入站响应队列读取响应并将其路由到插 件,在用于向套接字或其它外部请求源提供服务的插件中可能也有一些线程。 线程失败时并不总是显而易见的 如果这些线程中的一个(如响应分派线程)消失了,将会发生什么?因为插 件仍能够提交新消息,所以它们可能不会立即注意到某些方面出错了。消息仍将 通过各种输入源到达,并通过我们的应用程序提交到外部服务。因为插件并不期 待立即获得其响应,因此它仍没有意识到出了问题。最后,接收的响应将排满队 列。如果它们存储在内存中,那么最终将耗尽内存。即使不耗尽内存,也会有人 在某个时刻发现响应得不到传递 ― 但这可能需要一些时间,因为系统的其它方 面仍能 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |