繁体   English   中英

解决swingworker应用程序中的并发修改异常

[英]Solving a concurrent modification exception in a swingworker application

我正在编写一个应用程序,其中一些模拟在SwingWorker中运行。 在此模拟中,一些集保留了在SwingWorker的doInBackground()方法中修改的数据。 这些数据需要由GUI显示,但显然这会失败,因为一旦GUI开始访问集合,就会抛出并发修改异常,因为SwingWorker正在修改相同的集合。

如果SwingWorker不必等待GUI完成绘制数据,我将如何分享这些数据呢? 我是否必须复制数据然后发布()那些? 这会不会增加很多数据量(有很多数据)? 还有其他解决这个问题的方法吗?

这是一些简化的代码:

public class World {
    public Set<Foo> fooSet = new HashSet<Foo>();
}

public class Simulator extends SwingWorker<Void, Void> {
    private World       world;
    private WorldPanel  worldPanel;

    public Simulator(World world, WorldPanel worldPanel) {
        this.world = world;
        this.worldPanel = worldPanel;
    }

    @Override
    protected Void doInBackground() throws Exception {
        while (true) {
            doSomethingWithFooSet() //structurally modifies the set
            publish();
        }
    }

    @Override
    protected void process(List<Void> voidList) {
        worldPanel.repaint();
    }
}

public class WorldPanel extends JPanel {
    private final World             world;

    public WorldPanel(World world) {
        this.world = world;
    }

    @Override
    public void paintComponent(Graphics g) {
        drawWorld() //reads from fooSet in world
    }
}

不要误会我的意思,我理解为什么这不起作用,我只是想知道在这个设计中我应该做些什么才能做我想做的事情:访问我的模拟正在修改的相同数据。 process()是否在EDT上运行? 如果是这样,是否可以让process()更新WorldPanel用于绘制数据的world对象的副本中的集合?

您无法同时更新和显示世界对象,因此您有两种方法:按顺序更新和显示,或克隆数据以使更新和显示的数据不同。 要实现第一个变体,只需不要使用SwingWorker。 在第二个变体中,如果简单克隆整个世界是不可接受的,那么让后台线程不仅要计算世界的新状态,还要修改修改世界图像的命令。 Publish该命令,然后process它们以更新图片。

我会在gui中添加一个标志,它是否应显示/访问数据

最初将其设置为false,并且当您的工作人员完成重新加载具有切换标志的访问部分时

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM