2017-02-09 10 views
4

私はいくつかのアップスキルの一部としてREST APIを開発してきました。私の現在の実装では、ConcurrentHashMapにオブジェクトを挿入するときに、並行性の問題が少なくなっています。ConcurrentHashMapを使用する場合の同時処理の問題

私のコードは、消費されたJSONにIDが含まれているかどうかを確認します。いいえ、私は新しい一意のIDを作成し、オブジェクトを挿入します。はいの場合は、引き続きIDがマップに存在するかどうかを確認します。 IDを持つオブジェクトが存在しない場合は、オブジェクトを挿入します。

HashMapに一致するIDが含まれているかどうかをチェックしてオブジェクトを挿入するまでの間に、多くの同時POST要求が行われているときに問題が発生しています。生成されたIDを有する要求は、第1の要求が第2の要求のコードのgcdMap.get(obj.getId()) == nullgcdMap.put(obj.getId(), obj);の間で実行される場合に、IDが指定された要求によって潜在的に上書きされる可能性がある。私はこの問題を再現するためにThread.Sleep()を使用しています。

public static ConcurrentMap<Long, GCDObject> gcdMap = new ConcurrentHashMap<Long, GCDObject>(); 
@POST 

@Consumes(MediaType.APPLICATION_JSON) 
public GCDObject create(GCDObject obj) throws GCDRequestException { 
    obj.setTimestamp(LocalDateTime.now()); 
    obj.setResult(GCD.calculate(obj.getX(), obj.getY())); 

    if (obj.getId() != null) { // JSON contains ID 
     if (gcdMap.get(obj.getId()) == null) { // If map does not contain obj with ID already, 
      Thread.sleep(1000); 
      gcdMap.put(obj.getId(), obj); // Put obj into map. 
      return obj; 
     } else { // else map already contains ID, 
      throw new GCDRequestException(); 
     } 
    } else { // JSON contains no ID 
     obj.setId(buildId()); // Build ID 
     gcdMap.put(obj.getId(), obj); // Put into map 
     return obj; 
    } 
} 

私はロックの使用に関する提案を見ましたが、この問題を解決する方法で実装することはできませんでした。私が解決策を見つけ出すのに役立つ例、ドキュメンテーション、または記事は、非常に高く評価されます。

編集:以下のコメントで約3回欠けています。私は今それらを編集することはできませんが、私は気づいた!

+1

をあなたは、Java 8を使用していますか? – shmosel

+0

はい私はJava 8を使用しています。 – Afterfield

+3

putIfAbsentとgetOrDefaultのような他のConcurrentHashMapメソッドを試してみましたか? –

答えて

10

使用putIfAbsent()条件付きで挿入します。

if (gcdMap.putIfAbsent(obj.getId(), obj) == null) { // If map did not contain obj with ID already, 
    return obj; 
} else { // else map already contained ID, 
    throw new GCDRequestException(); 
} 
+0

私はputIfAbscent()に別のショットを与えました。それは私が望んでいたことをしています。私は最初に私のプロジェクトを再建することを忘れていたかもしれないと思っています。ありがとうございました! – Afterfield

関連する問題