当我尝试访问同步列表时,为什么我的线程会停止?

时间:2009-12-01 08:31:16

标签: java synchronized

出于某种原因,输出:

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

'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();

        }

    }

在我的调度程序中(这是代理设计),我检查'tasks'是否为空,然后调用doReturnToOriginalPos()。也许这只是一次又一次地发生,以至于其他方法没有机会修改它?

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

2 个答案:

答案 0 :(得分:6)

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

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

您也可以使用VisualVM获取堆栈转储,以达到相同的最终目标:

  

您可以使用Java VisualVM来获取   线程转储(堆栈跟踪)而a   本地应用程序正在运行拿一个   线程转储不会停止   应用。打印线程时   dump你得到一个线程的打印输出   包含线程状态的堆栈   Java线程。

     

在Java中打印线程转储时   VisualVM,该工具打印一个堆栈   跟踪活动线程的痕迹   应用。使用Java VisualVM来实现   拿一个线程转储可以很   在没有的情况下很方便   有一个命令行控制台   应用。您可以使用堆栈跟踪   帮助诊断一些问题   比如死锁或什么时候   应用程序挂起。

答案 1 :(得分:2)

是否有可能另一个线程正在对tasks进行同步锁定?