关于移动jMapViewer的java.util.ConcurrentModificationException

时间:2014-09-02 14:41:17

标签: java jmapviewer

我正在尝试每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());
    }
}

感谢您的帮助。

基兰

1 个答案:

答案 0 :(得分:0)

您可以使用SemaphoreMutex监视器(方法签名中包含synchronized)或锁来执行此操作strong>(对象上的synchronize)。存在无锁等待方法,但这些算法更复杂,仅在特殊情况下才有用。


<强>实施例

问题可能是map同时修改,使用,可写:

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());
    }
}

这导致只有一个Thread可以访问map(如果它运行此代码)。如果一个线程在synchronize块中,则所有其他线程在块的开头等待。

这种方法的一个问题是所谓的读者 - 写作者问题。大多数数据结构允许多个读者读取,但如果某些线程想要写东西(也修改一些东西),那么 Reader 就不能活性。在这种情况下,使用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();
   }
}

您最好使用finally块,这样即使抛出Exception,您仍然可以解锁,否则其他任何对象都无法进入关键部分