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;


    }
}

私がやろうとしているのは、クラス StoreMessage によって受信されたすべてのメッセージ オブジェクトを 1 分ごとに TreeMap に保存し、その TreeMap をシリアル化してそれを呼び出しているクラスに返し、次の 1 分間の TreeMap を作成/クリアして保存することです。他のメッセージ オブジェクト。
メッセージ クラスのメッセージ オブジェクトは、コマンドライン引数として入力される jms テキスト メッセージです。storeメソッドは別のクラスで呼び出されますが、メソッドreturning()は別のクラスで呼び出されます。両方のクラスをインスタンス化して実行すると、複数の引数を使用して例外が発生します

java.util.ConcurrentModificationException
at java.util.TreeMap$PrivateEntryIterator.nextEntry(TreeMap.java:1100)
at java.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 つだけ指定している場合、この例外は発生しません。しかし、何度も準拠すると、同じ例外が発生します。
次に、メッセージ オブジェクトが受信されると、それらは TreeMap に格納され、シリアル化されて返されることに気付きました。ツリー マップにメッセージを 1 分間保存してから、すべてをシリアル化する場合。

4

5 に答える 5

2

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

イテレータが使用されている場合のコレクションの同期について説明しますか?

于 2012-04-05T09:32:46.780 に答える
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;
}
于 2012-08-02T15:56:24.637 に答える
-1

使ってみてくださいCollections:

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

Map インスタンスを同期します。

于 2012-04-05T08:20:54.240 に答える