0

我正在编写一个应用程序,其中一些模拟在 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 用来绘制数据的世界对象副本中的集合?

4

2 回答 2

2

You cannot simultaneously update and display the world object, so you have two ways out: do update and displaying sequentially, or clone data so that updated and displayed data are different. To implement the first variant, just do not use SwingWorker. In the second variant, if simple cloning the whole world is unacceptable, let the background thread compute not just the new state of the world, but also commands to modify the world's image. Publish that commands and then process them to update the picture.

于 2012-10-21T12:16:53.847 回答
0

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

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

于 2012-10-21T09:33:25.720 回答