2017-02-22 8 views
1

私はこのコードにスタティックブロックで初期化された共有ハッシュマップを持っています。私はハッシュマップを公開しておらず、読み取り専用です(getおよびcontainsKey)。 これがスレッドセーフであるかどうかを確認したかったのです。Javaハッシュマップ読み取り専用スレッドセーフ

new MyLoader().load()リターンは完全にすべてのデータを初期化されたマップは、その後変更されることはありませんすべてのスレッドが同時にこのマップからデータを取得するために、それが安全であると仮定すると
public class MyClass { 
    private static final Map<String, MyObject> myMap; 

    static { 
     myMap = new MyLoader().load() 
    } 

    public MyClass() { 
     if (containsKey(someKey)) { 
      // do something 
     } 
     myMap.get(something) 
    } 

    static boolean containsKey(String key) { 
     // do some other stuff 
     return myMap.containsKey(key) 
    } 
} 
+0

他のスレッドが読み取り中にスレッドがマップを変更していない限り(キー/値のペアの追加または削除、または既存の値の変更)、スレッドセーフです。私は、スレッド化に関係なく問題を引き起こすため、キーオブジェクトを変更することは含まれませんでした。 –

+0

これは公開されておらず、クラス内で変更されていません –

+0

メソッドは、マップに書き込むアプリケーション全体で_only_ものを 'new MyLoader()。load()'メソッドで呼び出すのですか? 1つのコール? –

答えて

2

。 HashMapのJavadocは、「複数のスレッドが同時にハッシュマップにアクセスし、少なくとも1つのスレッドがマップを構造的に変更する場合は、外部と同期する必要があります。したがって、マップを変更しているスレッドがない場合は、同期させる必要はありません。安全対策として

、あなたの load()方法は不変性を強制する必要があります。

public Map<String, MyObject> load() { 
    Map<String, MyObject> mymap = new HashMap<>(); 
    mymap.put(...); 
    ... 
    return Collections.unmodifiableMap(mymap); 
} 

この方法で、あなたはあなたが慣れていないいくつかのコードでは、いくつかのスレッドが誤ってマップを変更するかもしれないことを心配する必要はありません。それはできません。

関連する問題