Я пытаюсь обновлять маркеры на 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());
}
}
Спасибо за вашу помощь.
Киран
Вы можете сделать это с помощью 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
вы все равно блокируете блокировку, иначе никакой другой объект не сможет войти в критический раздел.
rs
? Можете ли вы дать MWE?