移动jMapViewer时的java.util.ConcurrentModificationException

移动jMapViewer时的java.util.ConcurrentModificationException,java,jmapviewer,Java,Jmapviewer,我正在尝试每5秒更新一次jMapViewer上的标记。在您移动地图之前,这似乎工作正常。此时,它抛出一个java.util.ConcurrentModificationException 我相信这与试图同时访问地图标记列表的不同进程有关,但我不确定如何修复它 timer.scheduleAtFixedRate(new TimerTask() { @Override public void run() { loadUnits();

我正在尝试每5秒更新一次jMapViewer上的标记。在您移动地图之前,这似乎工作正常。此时,它抛出一个
java.util.ConcurrentModificationException

我相信这与试图同时访问地图标记列表的不同进程有关,但我不确定如何修复它

   timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            loadUnits();
        }
    }, 5 * 1000, 5 * 1000);

   private void loadUnits() {      
    String query = "SELECT callsign, currentlat,currentlon,previouslat,previouslon,    mobile, uniticon FROM unit WHERE isdeleted=0;";
    rs = DBase.runQuery(query);
    kit.removeAllMapMarkers();
    MapMarkerUnit x;
    try {
        while (rs.next()) {
           x = new MapMarkerUnit(rs.getDouble("currentlat"),rs.getDouble("currentlon"));
           if (rs.getInt("mobile") == 1) x.setMovement(true);
           else x.setMovement(false);
           x.setIconName(rs.getString("uniticon"));
           x.setPriority(1);
           kit.addMapMarker(x);
        }
    }
    catch (SQLException e) {
        System.out.print(e.toString());
    }
}
谢谢你的帮助


Kieran

您可以使用
信号量
互斥体
监视器(方法签名中带有
同步
)或
对象上的同步
)。也存在无锁和无等待的方法,但这些算法更复杂,只在特殊情况下有用


示例

问题可能是
映射
被同时修改,使用,可以编写:

synchronize(map) {
    map.removeAllMapMarkers();
    MapMarkerUnit x;
    try {
        while (rs.next()) {
           x = new MapMarkerUnit(rs.getDouble("currentlat"),rs.getDouble("currentlon"));
           if (rs.getInt("mobile") == 1) x.setMovement(true);
           else x.setMovement(false);
           x.setIconName(rs.getString("uniticon"));
           x.setPriority(1);
           map.addMapMarker(x);
        }
    }
    catch (SQLException e) {
        System.out.print(e.toString());
    }
}
这导致只有一个
线程
可以访问
映射
(如果它运行此代码)。如果一个线程在
synchronize
块中,则所有其他线程都在块的开头等待

这种方法的一个问题就是所谓的读者-作者问题。大多数数据结构都允许多个读卡器读取数据,但如果某个线程想要写入某些内容(也要修改某些内容),则任何读卡器都不能处于活动状态。在这种情况下,可以使用
ReadWriteLock

private ReadWriteLock rwl = new ReentrantReadWriteLock();

public void writeSomething() {
   rwl.writeLock().lock();
   try {
      //Modify/write something
   } finally {
      rwl.writeLock().unlock();
   }
}

public String readSomething() {
   rwl.readLock().lock();
   try {
      //Read something
   } finally {
      rwl.readLock().unlock();
   }
}

您最好使用
最后
块,这样即使抛出
异常
,您仍然可以解锁锁,否则其他对象将无法进入关键部分。

什么是
rs
?你能给出一个MWE吗?RS是一个从MySQL数据库中提取的结果集。对不起,MWE?这有点新。最简单的工作示例,换句话说,代码可以编译和实验…@CommuSoft谢谢-用更多的代码更新了我的问题。我正在看下面的代码——希望在这段代码和谷歌之间,我能够理解它。可能是另一种选择。进一步研究这个问题。map是类jMapViewer的对象。这将在列表中存储地图标记列表。然后,它迭代此操作以重新绘制地图标记。问题似乎是map.removeAllMarkers()会在发生这种情况时删除它们。上面的示例很有意义,但我不确定如何实现它。同步(映射)似乎不起作用,因为迭代器已经在映射中。@KieranS:在这种情况下,您应该在检索标记列表之前锁定
map
,只有在不再对该列表执行任何操作时才解锁(结束作用域)。这起作用-在单独的列表上执行操作。谢谢你的帮助和时间@基兰斯:你还应该检查一下,是否每次都会重复这个动作。锁可能导致死锁:两个或多个线程等待对方执行某个操作。