首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java SwingWorker挂起

Java SwingWorker挂起
EN

Stack Overflow用户
提问于 2009-11-25 04:26:06
回答 1查看 3.2K关注 0票数 2

我正在调试一些使用SwingWorker编写的代码,用于执行数值计算和图形用户界面更新的混合操作。SwingWorker挂起,并显示以下堆栈跟踪:

代码语言:javascript
复制
Full thread dump Java HotSpot(TM) Client VM (14.3-b01 mixed mode, sharing):

"SwingWorker-pool-3-thread-4" prio=6 tid=0x07fd7c00 nid=0x143c waiting on condition [0x0a33f000]
   java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at sum.ee.ui.modelviewer.ModelViewer$ModelAnimator.doInBackground(ModelViewer.java:940)
        at sum.ee.ui.modelviewer.ModelViewer$ModelAnimator.doInBackground(ModelViewer.java:877)
        at javax.swing.SwingWorker$1.call(SwingWorker.java:274)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at javax.swing.SwingWorker.run(SwingWorker.java:313)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:619)

"SwingWorker-pool-3-thread-3" prio=6 tid=0x07fd7000 nid=0x11a8 waiting for monitor entry [0x0a2af000]
   java.lang.Thread.State: BLOCKED (on object monitor)
        at java.awt.Component.resize(Component.java:2044)
        - waiting to lock <0x24b936a0> (a java.awt.Component$AWTTreeLock)
        at java.awt.Component.setSize(Component.java:2035)
        at java.awt.Component.resize(Component.java:2069)
        at java.awt.Component.setSize(Component.java:2060)
        at javax.swing.JViewport.setViewSize(JViewport.java:1038)
        at javax.swing.ViewportLayout.layoutContainer(ViewportLayout.java:183)
        at java.awt.Container.layout(Container.java:1421)
        at java.awt.Container.doLayout(Container.java:1410)
        at jsyntaxpane.components.LineNumbersRuler.updateSize(LineNumbersRuler.java:109)
        at jsyntaxpane.components.LineNumbersRuler.removeUpdate(LineNumbersRuler.java:203)
        at javax.swing.text.AbstractDocument.fireRemoveUpdate(AbstractDocument.java:243)
        at jsyntaxpane.SyntaxDocument.fireRemoveUpdate(SyntaxDocument.java:118)
        at javax.swing.text.AbstractDocument.handleRemove(AbstractDocument.java:608)
        at javax.swing.text.AbstractDocument.remove(AbstractDocument.java:576)
        at javax.swing.JEditorPane.setText(JEditorPane.java:1493)
        at sum.ee.ui.SourceCodePanel.clearSourcePane(SourceCodePanel.java:256)
        at sum.ee.ui.SourceCodePanel.access$100(SourceCodePanel.java:47)
        at sum.ee.ui.SourceCodePanel$1.stateChanged(SourceCodePanel.java:209)
        at sum.ee.ui.VisualizationAggregator.fireStateChanged(VisualizationAggregator.java:300)
        at sum.ee.ui.VisualizationAggregator.update(VisualizationAggregator.java:97)
        at sum.ee.ui.modelviewer.ModelViewer$ModelAnimator.doInBackground(ModelViewer.java:918)
        at sum.ee.ui.modelviewer.ModelViewer$ModelAnimator.doInBackground(ModelViewer.java:877)
        at javax.swing.SwingWorker$1.call(SwingWorker.java:274)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at javax.swing.SwingWorker.run(SwingWorker.java:313)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor

$Worker.run(ThreadPoolExecutor.java:908)在java.lang.Thread.run(Thread.java:619)

我的理解是图形用户界面的工作不应该在doInBackground()中完成,而应该在done()中完成。我执行了一个幼稚的实验,将doInBackground()中的所有代码都移到了done()中,但它仍然不起作用。对于如何解决这个问题,人们有什么建议可以给我吗?代码如下所示:

代码语言:javascript
复制
protected Void doInBackground() {
    isAnimating = true;
    resetButtonBackgrounds();
    backgroundColor = new Color(175, 255, 175);  // Soft Green

    JToggleButton b = null;
    for (final int index : modelIndices) {
        if (index == modelIndices.get(modelIndices.size() - 1)) {
            backgroundColor = defaultBackgroundColor;
        }
        if (!keepTrace) {
            // Resetting the backgrounds is necessary to have
            // individual display of the changing elements due to
            // the fact that there can be multiple nodes per
            // source line.  The reset works in combination
            // with updating from ModelViewer.this (as opposed
            // to the 'this' of ModelAnimator instances) due
            // to not sending an event to itself.  Furthermore,
            // if the event was sent from ModelAnimator, the model
            // indices are recalculated, causing a jump when multiple
            // element source lines are encountered.
            resetButtonBackgrounds();
        }
        aggregator.modelIndex(index);
        aggregator.update(ModelViewer.this);

        b = getButtonByIndex(index);
        scrollRectToVisible(b.getBounds());
        ModelViewer.this.repaint();
        try {
            StaticTools.sleepAtLeast(sleepTimeMilliseconds);
        } catch (final InterruptedException ex) {
            // continue with thread
        }
    }

    isAnimating = false;

    if ( b != null) {

        Color orig = b.getBackground();
        Color blink = Color.PINK;
        Color current = orig;
        for (int i = 0; i < 100; i++) {

            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
            }

            if (current == orig) {
                current = blink;
            } else {
                current = orig;
            }

            b.setBackground(current);
            ModelViewer.this.repaint();

        }
    }

    return null;
}

另一个线索是有两个SwingWorker线程在执行。它们能运行相同的线程吗?

更新:下面是执行SwingWorker的代码:

公共最终空动画(最终长delayBetweenUpdatesMilliseconds,最终列表modelIndices,最终布尔keepTrace,最终列表propertyChangeListeners) {

代码语言:javascript
复制
ModelAnimator modelAnimator =
        new ModelAnimator(delayBetweenUpdatesMilliseconds, modelIndices,
        keepTrace);
for (final PropertyChangeListener listener : propertyChangeListeners) {
    modelAnimator.addPropertyChangeListener(listener);
}

modelAnimator.execute();

}

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2009-11-25 05:11:43

这是对Swing EDT规则的失败。

SwingWorker的目的是在发生阻塞UI的UI事件时执行繁重的nonGUI任务,然后在结束时更新UI。

因此,您将在doInBackground()中实现举重操作;完成后,swing将在EDT上调用done(),您可以使用get()检索结果。

这里的问题是,您正在SwingWorker创建的新线程中执行图形用户界面工作。这可能会导致死锁和并发问题。

这包括创建所述GUI对象,即使您已经在EDT上,这些对象也应该在runnables中

操作,例如:

代码语言:javascript
复制
b = getButtonByIndex(index);

应该用InvokeandWait封装在可运行的。实际修改图形用户界面本身的东西尤其需要在它们自己的可运行文件中,即使是如果你已经在swing事件调度线程中响应按钮按下或更改,你就会冒着在你已经在处理的对象上工作的风险。

例如,swing在A上工作,并锁定A让你工作,让你在B上工作,尝试在A上锁定和工作

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1792700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档