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