3

「HashMap」を拡張する Subscriber という名前のクラスがあります。リストにはこのクラスの多くのインスタンスがあり、各インスタンスには一連のエントリがマップに設定されており、そのうちの 1 つが「ステータス」です。

私たちのプログラムは、サブスクライバーでメソッドを呼び出して「ステータス」値を更新しています。これは、HashMap への単純な書き込みを行います。

私たちのプログラムは問題なく数日 (数週間) 実行できますが、HashMap のデータを使用するシステムの他の部分で奇妙な動作が見られることがあります。1 つ以上の Subscriber インスタンスに重複したキーがあるようです。

jmap ダンプの作成に成功しました。ダンプに基づいて、VisualVM でダンプを確認すると、「ステータス」が 2 回設定されているように見えます。

VisualVM のスクリーンショット

現在、Java バージョンを実行しています: 1.7.0_25 (Oracle)

これはどのように可能ですか?または、VisualVM を間違って読んでいますか?

4

1 に答える 1

1

スレッドの問題とは別に、この結果への明確なルートがあります。

class Key implements CharSequence {

    private byte[] key;

    public Key(String key) {
        // Take a copy of the bytes of the string.
        this.key = key.getBytes();
    }

    @Override
    public int length() {
        return key.length;
    }

    @Override
    public char charAt(int index) {
        return (char) key[index];
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        return new Key(new String(key).substring(start, end));
    }

    // Allow the key to change.
    public void setKey(String newValue) {
        key = newValue.getBytes();
    }

    @Override
    public String toString() {
        return new String(key);
    }
}

public void test() {
    Map<CharSequence, String> testMap = new HashMap<>();
    Key aKey = new Key("a");
    Key bKey = new Key("b");
    testMap.put(aKey, "a");
    testMap.put(bKey, "b");
    bKey.setKey("a");
    System.out.println(testMap.keySet());
}

これは基本的に、マップのキーを可変にすることで、マップに追加したに変更できるようにします。

これはあなたが直面している問題ではないかもしれませんが (マルチスレッドの問題である可能性が高いです)、これは「私の HashMap に重複したキーがあるのはなぜですか?」という質問に対する本当の答えです。.

于 2014-11-24T12:21:52.263 に答える