题
出于某种原因,在此输出:
public void msgNeedParts() {
// Blabla...
System.out.println(name + ": Try to print 'tasks'...");
synchronized(tasks) {
System.out.println(name + ": Tasks--" + tasks);
System.out.println(name + ": Did I manage to print it?");
tasks.add(new BinToDump(feeder, binNum));
}
stateChanged();
}
刚打印出“GantryAgent:尝试打印‘任务’......”而不是下列任何消息。我猜线程莫名其妙试图访问同步列表“任务”时“卡住”,但我不知道为什么会这样。
'任务' 被声明和初始化这样的:
private List<BinToDump> tasks =
Collections.synchronizedList(new ArrayList<BinToDump>());
有人能指出我错过了什么?
啊!我怀疑可具有罪魁祸首:
/* If nothing left to do, return to original position. */
synchronized (tasks) {
if (tasks.isEmpty()) {
doReturnToOriginalPos();
}
}
在我的调度程序(这是一个代理设计),我检查,看看是否“任务”是空的,然后我打电话doReturnToOriginalPos()。也许这只是发生一遍又一遍如此之快,其他方法都没有机会对其进行修改?
这确实是问题!它不断获得所谓的如此之快,我的调度程序,没有别的可以访问“任务”。感谢所有帮助!
解决方案
东西对任务的锁。根据这是什么样的应用程序,你应该能够得到系统的完整的堆栈转储,但方法有所不同。例如,我想用CTRL-Break在大多数基于Windows的appservers会做到这一点,我想送Linux上的SIGQUIT将这样做。
一旦你得到一个堆栈转储,你可以看看通过它来尝试,并找出哪些其他线程具有对象的锁。
您也可以使用 VisualVM的得到一个堆栈转储,对于相同的最终目标:
您可以使用Java的VisualVM采取 线程转储(堆栈跟踪),而 本地应用程序运行。隔空 线程转储不会停止 应用。当您打印线 甩了你获得线程的打印输出 堆栈,包括线程状态为 的Java线程。
当您打印在Java线程转储 VisualVM的,该工具打印一个堆栈 的活动线程的痕迹 应用。使用Java的VisualVM到 采取线程转储可以很 便利的情况下,你不 具有用于一个命令行控制台 应用。您可以使用堆栈跟踪 以帮助诊断一些问题 如死锁或当 应用程序挂起。
其他提示
是否有可能另一个线程持有针对tasks
同步锁?