2

次の方法でハッシュ テーブルの値を検索する Java コードがあります。

class HTDemo {
    public static void main(String args[]) {
        Hashtable balance = new Hashtable();
        double bal;
        balance.put("John Doe", new Double(3434.34));
        balance.put("Tom Smith", new Double(123.22));
        balance.put("Jane Baker", new Double(1378.00));
        balance.put("Todd Hall", new Double(99.22));
        balance.put("Ralph Smith", new Double(-19.08));

        **System.out.println("John Doe's balance: " + balance.get("John Doe"));**
        **System.out.println("Tom Smith's balance: " + balance.get("Tom Smith"));**
        **System.out.println("Jane Baker's balance: " + balance.get("Jane Baker"));**
    }
 }

今、私はそれを複数のスレッドで実行したい、つまり、get メソッド (** 内) が同時に動作するようにコードを変更したい。誰でもそれを行う方法を手伝ってもらえますか。実際、実行中にハッシュテーブルを渡し、同時に実行するという問題に直面しています。

4

4 に答える 4

6

ハッシュテーブルは同期されているため、すでにスレッドセーフです。マルチスレッド環境でコードに安全にアクセスするには、他に何も必要ありません。

ただし、HashTable は廃止され、スレッド セーフ メカニズムが実装されている (すべてのメソッドが同期されている) ため、高度な同時実行環境ではパフォーマンスが非常に悪くなります。繰り返します。

結論: ConcurrentHashMap を使用し、可能であればジェネリックを使用します。

Map<String, Double> balance = new ConcurrentHashMap<String, Double> ();

コードの残りの部分は変更しないでください。

また、心に留めておく必要があることの 1 つは、スレッド セーフなデータ構造 (HashTable や ConcurrentMap など) を使用する場合でも、atomcity などの同時実行の問題に対処する必要があることです。

たとえば、次のように残高を確認して支払いを承認するとします。

double johnBalance = balance.get("John");
if(johnBalance > paymentAmount) 
    authorisePayment();
else
    declinePayment();

原子性の問題があります。John の口座の残高は、呼び出しbalance.get(...)と支払い承認の間で変更された可能性があります。

これがユース ケースの 1 つである場合は、追加の同期レイヤーを導入する必要があります。

于 2012-07-29T16:37:09.803 に答える
2

できません。HashTable のすべてのメソッドが同期されます。Javadoc を参照してください。HashMap を使用するか、言及していないスレッドセーフが必要な場合は ConcurrentHashMap を使用します。

于 2012-07-29T16:19:28.680 に答える
2

をご覧くださいConcurrentHashMap

...

取得の完全な同時実行と、更新の調整可能な予想同時実行をサポートするハッシュ テーブル。

...

これらの 3 行を並列化するには、次のようにします。

String[] users = { "John Doe", "Tom Smith", "Jane Baker" };
for (final String user : users) {
    new Thread() {
        public void run() {
            System.out.println(user + "'s balance: " + balance.get(user));
        }
    }.start();
}

実際にもう少し複雑なシナリオがある場合はExecutorService、関連するクラスを調べることをお勧めします。

于 2012-07-29T16:17:32.897 に答える
2

おそらく、ハッシュマップよりもハッシュテーブルを使用しているのは、マルチスレッド環境にアクセスしたいからです。これらの同期されたコレクションは、実際に同期の問題を解決できないため、現在は廃止されています。彼らは実際に追加または削除を原子化していました。しかし、それらは、追加する前にキーが存在するかどうかをマップで最初に確認する必要があるという単純なシナリオには対応していません。

Collection.synchronozimap() は、同時実行性の問題に対処するための一歩先を行っていましたが、集中的なマルチスレッド環境では失敗しました。

最終的に推奨される方法は、並行 API を使用することです。これらは、メソッド ConcurrentMap.putIfAbsent によって、上記で説明したようないくつかの問題に対処します。

于 2012-07-29T16:39:03.017 に答える