2014-09-02 14 views
1

我試圖每5秒更新一次jMapViewer上的標記。這似乎工作正常,直到你移動地圖。此時它會拋出java.util.ConcurrentModificationException移動jMapViewer java.util.ConcurrentModificationExceptionException

我認爲這是與嘗試同時訪問地圖標記列表的不同進程有關,但我不知道如何解決該問題。

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嗎? – 2014-09-02 14:43:52

+0

RS是從MySQL數據庫中提取的ResultSet。對不起MWE?有點新的這一點。 – KieranS 2014-09-02 14:46:09

+0

最小工作示例,換句話說,代碼可以編譯和實驗...... – 2014-09-02 14:46:22

回答

0

您可以在此使用SemaphoreMutex做,一個顯示器(在方法簽名​​)或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塊中,則所有其他線程將在塊的開始處等待。

這種方法的問題是所謂的讀者 - 作家問題。大多數數據結構允許被多個讀取器讀取,但是如果某些線程想要寫東西(修改某些內容),則沒有讀取器可以是活動的。在這種情況下,一個使用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 2014-09-02 18:55:47

+0

你上面的例子是有道理的,但我不知道如何實現它。同步(地圖)似乎不起作用,因爲迭代器已經在地圖內部了。 – KieranS 2014-09-02 18:56:39

+0

@KieranS:在這種情況下,您應該在檢索標記列表之前鎖定'map',並且如果不再對該列表執行任何操作,則僅解鎖(結束範圍)。 – 2014-09-02 19:01:14