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());
    }
}

ご協力いただきありがとうございます。

キーラン

4

1 に答える 1

0

これはSemaphore、、、モニター(メソッド シグネチャ内) またはロック(オブジェクト上)を使用して行うことができます。ロックフリーウェイトフリーのアプローチも存在しますが、これらのアルゴリズムはより複雑で、特別な状況でのみ有用です。Mutexsynchronizedsynchronize


問題はおそらく、ロック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アクセスできるのは 1 つだけになりますmap(このコードを実行した場合)。1 つのスレッドがsynchronizeブロック内にある場合、他のすべてのスレッドはブロックの先頭で待機します。

このアプローチの問題は、いわゆるReaders-Writers problemです。ほとんどのデータ構造は複数のReadersによる読み取りを許可しますが、一部のThreadが何かを書き込みたい場合 (何かを変更したい場合)、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

于 2014-09-02T14:45:48.697 に答える