1

出于某种原因,这个输出:

 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: Try to print 'tasks'...”,但不会打印以下任何消息。我猜测线程在尝试访问同步列表“任务”时会以某种方式“卡住”,但我不知道为什么会这样。

'tasks' 的声明和初始化如下:

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()。也许这只是一次又一次地发生得太快以至于其他方法没有机会修改它?

这确实是问题所在!它在我的调度程序中一直被调用得如此之快,以至于没有其他东西可以访问“任务”。感谢大家的帮助!

4

2 回答 2

6

有些东西锁定了任务。根据这是哪种应用程序,您应该能够获得系统的完整堆栈转储,但方法会有所不同。例如,我认为大多数基于 Windows 的应用服务器上的 CTRL-Break 都会这样做,我认为在 linux 上发送 SIGQUIT 也会这样做。

一旦获得堆栈转储,您可以查看它以尝试找出哪个其他线程对该对象具有锁定。

您还可以使用VisualVM获取堆栈转储,以实现相同的最终目标:

您可以在本地应用程序运行时使用 Java VisualVM 进行线程转储(堆栈跟踪)。进行线程转储不会停止应用程序。当您打印线程转储时,您将获得线程堆栈的打印输出,其中包括 Java 线程的线程状态。

在 Java VisualVM 中打印线程转储时,该工具会打印应用程序活动线程的堆栈跟踪。在您没有应用程序的命令行控制台的情况下,使用 Java VisualVM 进行线程转储会非常方便。您可以使用堆栈跟踪来帮助诊断一些问题,例如死锁或应用程序何时挂起。

于 2009-12-01T08:40:39.770 回答
2

是否有可能另一个线程持有同步锁tasks

于 2009-12-01T08:34:57.660 回答