1

I'm trying to update markers on a jMapViewer once every 5 seconds. This seems to be working fine until you move the map. At this point it throws a java.util.ConcurrentModificationException.

I believe this is to do with the different processes trying to access the map markers list at the same time but I'm not sure how to fix it.

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

Thanks for your help.

Kieran

4

1 回答 1

0

您可以使用Semaphore, Mutex,监视器synchronized在方法签名中)或synchronize在对象上)来执行此操作。也有无锁和无等待方法,但这些算法更复杂,只在特殊情况下才有用。


例子

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

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块中,则所有其他线程在块的开始处等待。

这种方法的一个问题是所谓的Readers-Writers 问题。大多数数据结构允许由多个Reader 读取,但如果某个Thread想要写一些东西(也修改一些东西),则没有Reader可以处于活动状态。在这种情况下,使用 a 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抛出了你仍然可以解锁锁,否则没有其他对象能够进入临界区

于 2014-09-02T14:45:48.697 回答