私はいくつかのアップスキルの一部としてREST APIを開発してきました。私の現在の実装では、ConcurrentHashMapにオブジェクトを挿入するときに、並行性の問題が少なくなっています。ConcurrentHashMapを使用する場合の同時処理の問題
私のコードは、消費されたJSONにIDが含まれているかどうかを確認します。いいえ、私は新しい一意のIDを作成し、オブジェクトを挿入します。はいの場合は、引き続きIDがマップに存在するかどうかを確認します。 IDを持つオブジェクトが存在しない場合は、オブジェクトを挿入します。
HashMapに一致するIDが含まれているかどうかをチェックしてオブジェクトを挿入するまでの間に、多くの同時POST要求が行われているときに問題が発生しています。生成されたIDを有する要求は、第1の要求が第2の要求のコードのgcdMap.get(obj.getId()) == null
とgcdMap.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回欠けています。私は今それらを編集することはできませんが、私は気づいた!
をあなたは、Java 8を使用していますか? – shmosel
はい私はJava 8を使用しています。 – Afterfield
putIfAbsentとgetOrDefaultのような他のConcurrentHashMapメソッドを試してみましたか? –