【问题标题】:Threading and deadlock in Swing applicationSwing 应用程序中的线程和死锁
【发布时间】:2012-03-21 17:56:06
【问题描述】:

我在我维护的 Swing 应用程序中遇到了死锁,虽然我有一个似乎可行的解决方法,但我不确定我是否理解我在做什么并且没有隐藏一个竞争条件稍后可能会再次弹出。

线程跟踪显示死锁发生在两个线程之间,AWT-EventQueue-0 和 AWT-EventQueue-1。我的第一个问题是,如果其中任何一个是臭名昭著的事件调度线程。两个线程的堆栈跟踪底部都有以下内容:

at java.awt.EventDispatchThread.run(EventDispatchThread.java:138)

我认为问题的根源在于应用程序类将域数据与图形组件混合在一起,在这种情况下,两个线程都试图锁定 java.awt.Component$AWTTreeLock 和我自己的一个对象(比如 X)。我的解决方法是在 X 被锁定的地方使用SwingUtilities.invokeLater(),即使它已经在 EDT 上。根据 Javadoc,这意味着调用“推迟到所有待处理事件都已处理完毕”。但是,我不太确定这是否真的是一个解决方案,而且无论如何我都不清楚为什么似乎有两个 EDT。

谁能解释发生了什么?我可以尝试提供代码的精简版本,但可能需要一些时间来编辑不相关的复杂问题。

【问题讨论】:

  • 在这个过程中你会打开一个模态对话框吗?还是您的代码推送了一个新队列?
  • 啊,是的!我得看看它是如何工作的。它不会取代现有的队列吗?为什么会导致两个 AWT-EventQueue 线程?

标签: java swing thread-safety


【解决方案1】:

感谢 Yishai 为我指明了正确的方向。该应用程序正在实例化它自己的java.awt.EventQueue 子类并使用Toolkit.getDefaultToolkit().getSystemEventQueue().push(newQueue) 替换原始队列。原始队列必须仍在其线程AWT-EventQueue-0 上处理任务,同时事件开始到达线程AWT-EventQueue-1 上的新队列,从而导致死锁。

【讨论】:

    【解决方案2】:

    您是否在任何地方创建线程?如果是,考虑使用

    http://docs.oracle.com/javase/7/docs/api/javax/swing/SwingWorker.html

    http://docs.oracle.com/javase/7/docs/api/javax/swing/Timer.html

    相反,它与 Swing 配合得很好。

    【讨论】:

    • 不,没有明确创建任何新线程。只是一些初始化主线程(其中一些我已经使用 invokeLater 移到了 EDT)和 Swing 组件的事件处理程序,当然在 EDT 上调用它们。无论如何,这就是它应该的样子。
    猜你喜欢
    • 1970-01-01
    • 2021-03-23
    • 2014-07-19
    • 1970-01-01
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多