2012-04-05 3 views
0
public class StoreMessage extends Thread implements Serializable{ 

    private static long start_nanotime=System.nanoTime(); 
    private static int timeToRun = 60000; 
    private static byte[] b=null; 
    private static long startTime = System.currentTimeMillis(); 
    private static long runUntilMillis = System.currentTimeMillis() + timeToRun; 
    public static Map <Long,Message> map1=new TreeMap<Long,Message>(); 
public static void store(Message message)throws Exception{ 
     while (true) { 
      long now = System.currentTimeMillis(); 
      if (now >= runUntilMillis) { 
       break; 
      } 
      long precise_time=TimeUnit.MILLISECONDS.toNanos(now)+(System.nanoTime()-start_nanotime); 
      map1.put(precise_time, message); 
      } 
    } 
public static byte[] returning()throws Exception 
    { 

     b=serializer.serialize(map1); 
     System.out.println(b); 
     map1.clear(); 
     return b; 


    } 
} 

は、すべて私のメッセージは、TreeMapのに一分ごとにクラスStoreMessageで受信されたオブジェクトストアで、TreeMapのクラスの呼び出し元に戻すことをシリアライズ他のメッセージオブジェクトを格納する次の分のTreeMapを作成/クリアします。
メッセージクラスのメッセージオブジェクトは、コマンドライン引数として入力されるjmsテキストメッセージです。 storeメソッドは別のクラスで呼び出され、returningメソッドは別のクラスで呼び出されます。両方のクラスは、インスタンス化およびJavaでjava.util.TreeMapの$ PrivateEntryIterator.nextEntry(TreeMap.java:1100) でjava.util.ConcurrentModificationExceptionが 私に例外java.util.ConcurrentModificationExceptionが

を与え、複数の引数を指定して、実行します.util.TreeMap $ EntryIterator.next(TreeMap.java:1136) at java.util.TreeMap $ EntryIterator.next(TreeMap.java:1131) at java.util.TreeMap.writeObject(TreeMap.java:2250)

なぜですか?特に、私は地図をクリアしています。コマンドライン引数を1つだけ指定している場合、この例外は発生しません。しかしそれが何度も遵守されるならば、私は同じ例外を受ける。
2つ目は、受信したメッセージオブジェクトがTreeMapに格納されてシリアライズされて返されることに気付きました。とき私は1分のメッセージを格納し、その後、全体のロットをシリアル化するツリーマップをしたい。

public static Map <Long,Message> map1 = 
Collections.synchronizedMap(new TreeMap<Long,Message>()); 

をごMapインスタンスを同期させるために:

+0

http://docs.oracle.com/javase/6/docs/api/java/util/ConcurrentModificationException.html? – claesv

答えて

-1

Collectionsを使用してみてください。

+3

Collections.synchronizedMap()はConcurrentModificationExceptionから保護しないため、これは明らかに間違った答えです。 – yurgis

2

他の回答は近いですが、私は完全ではないと思います。スローされたCMEを見ると、それはTreeMapイテレータにあります。これは、synchronizedMapにしてもスレッドセーフではありません。反復中にTreeMapを明示的に同期させる必要があります(この場合、シリアライゼーションのようです)。理論的には

Explain synchronization of collections when iterators are used?

0

あなたも同期マップでメッセージを失う可能性があります。 System.out.println()が進行中のときにストアが呼び出された場合。それはシリアライズされた後ですが、クリアされる前です。

だから私はあなたがマップ上で同期させることができると思います(私はそれをテストしていない):

public static void store(Message message) throws Exception { 
    while (true) { 
     long now = System.currentTimeMillis(); 
     if (now >= runUntilMillis) { 
      break; 
     } 
     long precise_time = TimeUnit.MILLISECONDS.toNanos(now) 
       + (System.nanoTime() - start_nanotime); 
     synchronized (map1) { 
      map1.put(precise_time, message); 
     } 
    } 
} 

public static byte[] returning() throws Exception { 

    synchronized (map1) { 
     b = serializer.serialize(map1); 
     System.out.println(b); 
     map1.clear(); 
    } 
    return b; 
} 
2

java.util.concurrent.ConcurrentSkipListMapはスレッドセーフTreeMapの実装であり、それは

Map<String, String> treeMap = new ConcurrentSkipListMap<String, String>(); 
自然順序付けを維持します次のように

我々はまた、変更不可能(読み取り専用)バージョンを入手することができます

TreeMap tM = new TreeMap(); 
Map tM2 = Collections.unmodifiableMap(tm1); 

マップtM2は読み取り専用です。

0

パーティーのために少し遅れが、それでも、

@FlinborはConcurrentSkipListMapは、このような状況で移動するための方法である、指摘したように。それは依然として、または自然に、またはコンパレータを介して注文され、アクセス時刻および修正時刻は、ConcurrentSkipListMapおよびTreeMap-O(log(n))の両方で同じです。しかし、同期のために少し遅くなる可能性があります。

のTreeMapのイテレータはがフェイルファスト、彼自身のremove()方法以外による構造変更後の反復の作成があったという意味ですが。 ConcurrentSkipListMapのイテレータは、イテレータの作成時または作成時のある時点でマップの状態を反映する、弱く一貫性のある、弱い一貫性のある要素を返す、

です。それらはConcurrentModificationExceptionをスローしません。

関連する問題