2014-09-02 2 views
1

Я пытаюсь обновлять маркеры на jMapViewer один раз каждые 5 секунд. Кажется, это работает нормально, пока вы не переместите карту. В этот момент он выбрасывает java.util.ConcurrentModificationException.java.util.ConcurrentModificationException при перемещении jMapViewer

Я считаю, что это связано с различными процессами, пытающимися получить доступ к списку маркеров карт одновременно, но я не уверен, как это исправить.

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? Немного новичок в этом. – KieranS

+0

Минимальный рабочий пример, другими словами код, который можно скомпилировать и поэкспериментировать с ... –

ответ

0

Вы можете сделать это с помощью Semaphore, Mutex, а мониторsynchronized в подписи метода) или замок (synchronize на объекте). Существует lock-free и wait-free также подходит, но эти алгоритмы более сложны и полезны только при особых обстоятельствах.


Примеры

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

Проблема с этим подходом - так называемая проблема Readers-Writers. Большинство хранилищ данных можно читать несколькими Читателями, но если некоторые Thread хотите что-то написать (изменить что-то тоже), no 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

Вниманию этой проблемы. map - объект класса jMapViewer. Здесь хранится список маркеров карты в списке . Затем он выполняет итерацию, чтобы перерисовать маркеры карт. Проблема заключается в том, что map.removeAllMarkers() удаляет их, пока это происходит. – KieranS

+0

Ваш пример выше имеет смысл, но я не уверен, как его реализовать.synchronize (map) не работает, поскольку итератор уже внутри карты. – KieranS

+0

@KieranS: в этом случае вы должны заблокировать «карту» перед извлечением списка маркеров и только разблокировать (завершить область), если в этом списке больше действий не будет. –

Смежные вопросы