java.util.ConcurrentModificationException при перемещении jMapViewer

1

Я пытаюсь обновлять маркеры на jMapViewer каждые 5 секунд. Кажется, это работает нормально, пока вы не переместите карту. В этот момент он выдает 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
    Что такое rs ? Можете ли вы дать MWE?
  • 0
    RS - это ResultSet, извлеченный из базы данных MySQL. Извините, MWE? Немного нового в этом.
Показать ещё 3 комментария
Теги:
jmapviewer

1 ответ

0
Лучший ответ

Вы можете сделать это с помощью Semaphore, Mutex, монитора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, все остальные потоки ждут в начале блока.

Проблема с этим подходом - так называемая проблема читателей-писателей. Большинство структур данных позволяют читать несколько читателей, но если какой-то поток хочет что-то написать (что-то изменить), ни один 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 вы все равно блокируете блокировку, иначе никакой другой объект не сможет войти в критический раздел.

  • 0
    Рассматривая эту проблему дальше. Карта является объектом класса jMapViewer. Это хранит список маркеров карты в List <MapMarker>. Затем он проходит через это, чтобы перерисовать маркеры карты. Проблема заключается в том, что map.removeAllMarkers () удаляет их, пока это происходит.
  • 0
    Ваш пример выше имеет смысл, но я не уверен, как это реализовать. синхронизация (карта) не работает, поскольку итератор уже находится внутри карты.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню