简体   繁体   English

移动jMapViewer时出现java.util.ConcurrentModificationException

[英]java.util.ConcurrentModificationException on moving jMapViewer

I'm trying to update markers on a jMapViewer once every 5 seconds. 我正在尝试每5秒更新一次jMapViewer上的标记。 This seems to be working fine until you move the map. 在您移动地图之前,这似乎工作正常。 At this point it throws a java.util.ConcurrentModificationException . 此时,它将引发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 基兰

You can do this using a Semaphore , Mutex , a monitor (with synchronized in the method signature) or a lock ( synchronize on object). 您可以使用SemaphoreMutex监视器 (在方法签名中synchronized )或 (在对象上synchronize )来执行此操作。 There exist lock-free and wait-free approaches as well, but these algorithms are more complex and are only useful under special circumstances. 也存在无锁和无 等待的方法,但是这些算法更加复杂,仅在特殊情况下有用。


Examples 例子

The problem is probably that map is modified concurrently, using a lock , one can write: 问题可能是使用lock可以同时修改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());
    }
}

This results in the fact that only one Thread can access map (if it runs this code). 这导致以下事实:只有一个Thread可以访问map (如果它运行此代码)。 If one thread is in the synchronize block, all other threads wait at the beginning of the block. 如果在synchronize块中有一个线程,则所有其他线程在该块的开始处等待。

A problem with this approach is the so called Readers-Writers problem . 这种方法的问题是所谓的“ 读者—作家”问题 Most datastructures allow to be read by multiple Readers , but if some Thread want to write something (modify something as well), no Reader can be active. 大多数数据结构都允许由多个Reader读取 ,但是如果某个线程想要写入某些内容(也修改某些内容),则没有任何Reader可以处于活动状态。 In that case one uses a ReadWriteLock : 在这种情况下,将使用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();
   }
}

You better use finally blocks so that even if an Exception is thrown you still unlock the lock, otherwise no other object will be able to enter the critical section . 你最好使用finally块,这样,即使Exception被抛出你还是解除锁定,否则没有其他物体就可以进入临界区

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM