我有一个多线程应用程序。有几条消息即将发送到应用程序,并在分离的线程中处理。为此,我使用包java.util.concurrent中的类ThreadPoolExecutor和FutureTask。
我偶尔会在应用程序中遇到一些死锁。当发生死锁时我想中断阻塞线程,我想记录这个线程的堆栈跟踪,以便以后可以解决死锁。
有没有什么办法可以在Java中找到该线程之外的线程的堆栈跟踪?
答案 0 :(得分:5)
请参阅here了解如何生成堆栈跟踪,包括如何以编程方式执行此操作。在控制台中, Ctrl + Break 会将堆栈跟踪转储到stdout。有关详细信息,另请参阅this SO question。
答案 1 :(得分:5)
您可以在应用程序中不时记录所有线程的堆栈跟踪(或在杀死进程之前)。要做到这一点:
Map<Thread, StackTraceElement[]> m = Thread.getAllStackTraces();
for(Map.Entry<Thread, StackTraceElement[]> e : m.entrySet()) {
log(e.getKey().toString());
for (StackTraceElement s : e.getValue()) {
log(" " + s);
}
}
当运行夜间自动化测试时,有时一些测试用例会陷入僵局。我添加了一个等待30分钟的“TimeBomb”守护程序线程,然后如上所述记录所有堆栈跟踪。
答案 2 :(得分:4)
在进入死锁区域之前,请设置一个字段,如
thread = Thread.currentThread();
在监控线程中,您可以执行thread.getStackTrace();以随时获取该线程的堆栈跟踪。
答案 3 :(得分:2)
您使用JStack。这是一个很好的blog entry,它详细说明了如何获得堆栈跟踪。
答案 4 :(得分:0)
我不确定您是希望从同一JVM内部还是外部获取堆栈跟踪,但如果您希望使用外部工具获取堆栈跟踪,以下内容将有所帮助:
答案 5 :(得分:0)
发生死锁时我想中断阻塞线程......
你可以实现一个周期性任务来检查死锁(其中死锁是java内在的或基于Lock
)并在方案中涉及的所有线程上调用interrupt
。但是,这并不能保证它能解决您的问题。它可能会再次发生。有关详细信息,请参阅Dr Heinz's article on a deadlock detector。
如果确实如此,则无法保证interrupt
甚至可以释放这样的被阻止进程。它是一种更好的方法,可以首先避免死锁情况,例如,使用具有超时和重试策略的锁定或“先尝试购买”方法。
我想记录这个线程的堆栈跟踪......
如果您想以编程方式执行此操作,请再次按照Heinz博士的示例进行操作。如果没有,只需在发现问题时生成线程转储。
有没有什么办法可以在Java中找到该线程之外的线程的堆栈跟踪?
是和否。您可以从其他VM转储线程,但是它们的堆栈跟踪可能没有您想象的那样有用于确定死锁的原因。如果检测到真正的死锁(由JVM本身在您的应用程序VM的线程转储上),您应该拥有调试原因所需的一切(或多或少)。