1

HashMap からオブジェクトを削除し、新しいキーを使用して同じオブジェクトを元に戻すことに関連していると思われる断続的な障害のトラブルシューティングを試みています。私の HashMap は次のように作成されます。

transactions = new HashMap<Short, TransactionBase>();

再割り当てを行うコードは次のとおりです。

transactions.remove(transaction.tran_no);
transaction.tran_no = generate_transaction_id();
transactions.put(transaction.tran_no, transaction);

私が見ている断続的な動作は、この直後に実行されるコードで、トランザクション オブジェクトが検索可能であることに依存していて、新しいトランザクション ID を使用してトランザクション オブジェクトを見つけられないように見えることです。ただし、将来のある時点で、トランザクションを見つけることができます。ストローを引っ張ると、この種の動作を引き起こす可能性のある put() または remove の非同期効果はありますか?

私の知る限りでは、コンテナーは 1 つのスレッドのみによってアクセスされていることに注意してください。クラス HashMap が「同期」されていないというドキュメントを既に読んでいます。

4

9 に答える 9

6

アイテムの存在を確認するたびに、必ず ashortまたはShort argumenttoMap.get()またはMap.contains()?を使用していると思います。

これらのメソッドは Object 引数を取るので、それらを渡すintと に変換され、IntegerそれらはすべてShortキーを持つため、Map 内のどの項目とも一致しません。

于 2009-01-14T21:25:43.797 に答える
4

HashMap クラスには「非同期」効果はありません。そこに何かを入れるとすぐに、そこにあります。スレッドの問題がないことを確認するために、二重および三重にチェックする必要があります。

他に考えられる唯一のことは、HashMap のコピーをどこかに作成していることです。オリジナルに何かを追加しても、コピーは明らかに影響を受けません。その逆も同様です。

于 2009-01-14T21:10:38.087 に答える
2

1 つの提案... HashMap へのアクセスに焦点を当てていますが、generate_transaction_id() がスレッド セーフであるかどうか、または予期しない方法で動作しているかどうかも確認する必要があるのだろうかと思います。

于 2009-01-14T22:44:56.117 に答える
2

オーバーライドしましたが、モデル オブジェクトではオーバーライドequals()しませんでしhashCode()たか? どうcompareTo()ですか?これらを間違えると、コレクションは実に奇妙な動作をします。

equals()およびcompareTo()のJava Practices を確認してください。

于 2009-01-14T23:01:23.043 に答える
1

HashMapつまり、はスレッド セーフではないことがわかります。1 つのスレッドだけがアクセスしていると確信していますか? 結局のところ、断続的な障害は頻繁にスレッド化に関連しています。Collections.synchronizedMap()そうでない場合は、次のようにラップできます。

Collections.synchronizedMap(transactions);

その可能性を排除できるように、いつでも試すことができます。

これは、すべてのメソッドが同期されたマップで元のマップをラップするだけであることに注意してください。アクセスが局所化されている場合は、同期ブロックの使用を検討することをお勧めします。

于 2009-01-14T21:01:14.347 に答える
1

この generate_transaction_id() 関数は何をしますか? 16 ビットの GUID のようなものを生成している場合、簡単にハッシュの衝突が発生する可能性があります。スレッド化と組み合わせると、次のようになります。

T1: transaction1.tran_no = generate_transaction_id();    => 1729
T2: transaction2.tran_no = generate_transaction_id();    => 1729
T1: transactions.put(transaction1.tran_no, transaction1); => map.put(1729, transaction1)
T2: transactions.put(transaction2.tran_no, transaction2); => map.put(1729, transaction2)
T1: int tran_no = transactions.get(1729);               => transaction2
T1: transactions.remove(transaction.tran_no);           => map.remove(1729)
T2: int tran_no = transactions.get(1729);               => null

もちろん、これは「あなたの知る限り」の部分が真実でない場合にのみ解決策になる可能性があります。

于 2009-01-14T23:12:32.987 に答える
0

他の人が観察しているように、HashMapが1つのスレッドだけでアクセスされているかどうかを知る必要があります。CollectionSpyは、すべてのコンテナーについて、アクセスを実行するスレッドの数を即座に確認できる新しいプロファイラーです。詳細については、 www.collectionspy.comを参照してください。

于 2009-07-03T19:29:44.930 に答える
0

スレッド化についてはすでにいくつかの回答で言及されていますが、複数のスレッドで使用されるオブジェクトの可視性の問題については考慮しましたか? オブジェクトをあるスレッドのコレクションに入れると、コレクションで適切に同期しない限り、他のスレッドに「発行」されない可能性があります (そして非常に一般的です)。

スレッドとロック

Java での同期とスレッド セーフ

于 2009-01-14T23:25:14.367 に答える