HashMap対ConcurrentHashMap対。 SynchronizedMap –JavaでHashMapを同期する方法

公開: 2015-01-29

ConcurrentHashMap対をCrunchifyします。 SynchronizedMapの例 HashMapは、Javaの非常に強力なデータ構造です。 私たちは毎日、ほとんどすべてのアプリケーションでそれを使用しています。 スレッドセーフキャッシュを実装する方法、ハッシュマップを配列リストに変換する方法について以前に書いた例はかなりありますか?

上記の両方の例でHashmapを使用しましたが、これらはHashmapの非常に単純なユースケースです。 HashMap is a non-synchronizedコレクションクラスです。

以下の質問はありますか?

  • ConcurrentHashMapとCollections.synchronizedMap(Map)の違いは何ですか?
  • ConcurrentHashMapとCollections.synchronizedMap(Map)のパフォーマンスの違いは何ですか?
  • ConcurrentHashMapとCollections.synchronizedMap()
  • 人気のあるHashMapとConcurrentHashMapのインタビューの質問

このチュートリアルでは、上記のすべてのクエリを確認し、ハッシュマップを同期できるwhy and howを説明します。

なんで?

Mapオブジェクトは、一意に識別されるkeyとマップされたvalueの組み合わせによって形成された要素を格納する連想コンテナです。 異なるスレッドでキー値を変更または読み取りたい可能性のある非常に並行性の高いアプリケーションがある場合は、並行ハッシュマップを使用するのが理想的です。 最良の例は、同時読み取り/書き込みを処理するプロデューサーコンシューマーです。

では、スレッドセーフマップとはどういう意味ですか? multiple threadsが同時にハッシュマップにアクセスし、少なくとも1つのスレッドがマップを構造的に変更する場合は、コンテンツの表示に一貫性がないように、 must be synchronized externally

どのように?

HashMapを同期する方法は2つあります

  1. JavaコレクションsynchronizedMap()メソッド
  2. ConcurrentHashMapを使用する

ConcurrentHashMap

  • プロジェクトで非常に高い同時実行性が必要な場合は、ConcurrentHashMapを使用する必要があります。
  • whole mapを同期しなくてもスレッドセーフです。
  • 書き込みがロックで行われている間、読み取りは非常に高速に発生する可能性があります。
  • オブジェクトレベルでのロックはありません。
  • ロックは、ハッシュマップバケットレベルではるかに細かい粒度で行われます。
  • ConcurrentHashMapは、別のスレッドが反復しているときに1つのスレッドがそれを変更しようとしても、 ConcurrentModificationExceptionをスローしません。
  • ConcurrentHashMapは、多数のロックを使用します。

SynchronizedHashMap

  • オブジェクトレベルでの同期。
  • すべての読み取り/書き込み操作はロックを取得する必要があります。
  • コレクション全体をロックすると、パフォーマンスのオーバーヘッドが発生します。
  • これにより、基本的に、マップ全体への1つのスレッドのみにアクセスできるようになり、他のすべてのスレッドがブロックされます。
  • 競合が発生する可能性があります。
  • SynchronizedHashMapはIteratorを返しますが、これは同時変更で失敗します。

それでは、コードを見てみましょう

  1. クラスCrunchifyConcurrentHashMapVsSynchronizedHashMap.java作成します
  2. HashTable、SynchronizedMap、CrunchifyConcurrentHashMapごとにオブジェクトを作成します
  3. マップから500kエントリを追加および取得します
  4. 開始時間と終了時間、および表示時間をミリ秒単位で測定します
  5. ExecutorServiceを使用して、 5 threadsを並行して実行します

Javaコードは次のとおりです。

  • shutdown()は、エグゼキュータサービスが着信タスクをこれ以上受け取らないことを意味します。
  • awaitTermination()は、シャットダウン要求の後に呼び出されます。

したがって、最初にserviceExecutorをシャットダウンしてから、ブロックしてスレッドが終了するのを待つ必要があります。

Eclipseコンソールの結果: