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


谢谢你的帮助。

基兰

最佳答案

您可以使用SemaphoreMutex,监视器(方法签名中带有synchronized)或锁(对象上的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块中有一个线程,则所有其他线程在该块的开头等待。

这种方法的问题是所谓的“读者-作家”问题。大多数数据结构都允许多个读取器读取,但是如果某个线程想要写入某些内容(也要修改某些内容),则没有任何读取器可以处于活动状态。在这种情况下,使用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,您仍然可以解锁该锁,否则其他任何对象将无法进入关键部分。

09-26 12:35