[英]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.