先看代码:
private class TrustingPoolWorker extends Thread {
public void run() {
IncomingResponse ir;
while (true) {
ir = (IncomingResponse) queue.getNext();
PlugIn plugIn = findPlugIn(ir.getResponseId());
if (plugIn != null)
plugIn.handleMessage(ir.getResponse());
else
log("Unknown plug-in for response " + ir.getResponseId());
}
}
}
能看出什么地方会出现问题,尤其是线程泄露吗?
当线程抛出未捕获的异常或错误时它们可能消失;意外线程死亡的最常见根源是 RuntimeException
(如 NullPointerException
、ArrayIndexOutOfBoundsException
等)。
在我们的示例应用程序中,在通过调用插件对象上的 incomingResponse()
将响应传递回插件时,可能抛出 RuntimeException
。插件代码可能是由第三方编写的,或者可能是在编写完应用程序之后编写的,因此应用程序编写者不可能审核其正确性。如果一些插件抛出 RuntimeException
时某些响应服务线程会终止,这意味着一个出错的插件会使整个系统崩溃。遗憾的是,这种脆弱性很常见。
意外线程死亡的最常见根源是 RuntimeException
的结果很明显,并且对发生异常的位置有明确的堆栈跟踪,这提供了问题通知以及解决问题的有用信息。但是,在多线程应用程序中,由于未查出的异常,线程会无声无息地死亡
— 使得用户和开发人员对于发生的问题和为什么发生这些问题毫无头绪。
private class SaferPoolWorker extends Thread {
public void run() {
IncomingResponse ir;
while (true) {
ir = (IncomingResponse) queue.getNext();
PlugIn plugIn = findPlugIn(ir.getResponseId());
if (plugIn != null) {
try {
plugIn.handleMessage(ir.getResponse());
}
catch (RuntimeException e) {
// Take some sort of action;
// - log the exception and move on
// - log the exception and restart the worker thread
// - log the exception and unload the offending plug-in
}
}
else
log("Unknown plug-in for response " + ir.getResponseId());
}
}
}