HashMapの同時問題
3256 ワード
前のコード
実行結果:
次の2つのシナリオを試します.
a.HashMapをConcurrentHashMapに交換して実行する.
b.HashMapを使用する、第1セグメントEXECUTORを注釈する.executeのコードを実行します.
結果は次のとおりです.
案aは間違いを報告しないに違いない.シナリオbはこの間違いを報告しないはずだが、この間違いを報告する可能性は極めて小さい.
適用シーン:
取引の支払いイベントが来て、イベントのタイプはHashMapで、私達はカードの情報、IP情報などに対して情報の補完を行う必要があって、スレッドプールを通じて同時に情報の補完を実行する過程の中で、各スレッドの内部でmapを実行しました.put(key,value)の操作により、高同時で異常javaが投げ出す可能性がある.util.ConcurrentModificationException.(出現確率が低い)
このときスレッドでmapが実行する場合.keySet()操作、map中のデータを遍歴すると、異常javaが発生する.util.ConcurrentModificationExceptionの確率が高いです.
HashMapを使用すると、スレッドが安全ではないことがわかりますが、どのような問題が発生する可能性がありますか?
a.putのデータが失われた.
b.removeのデータは消去されず、依然として存在する.
c.HashMap resizeによるパフォーマンスの問題.
d.getデータの場合、デッドサイクルが発生します.
ソリューション:
ConcurrentHashMapがおすすめです.
では、何が原因なのでしょうか.
以下の2つの文章を参照することができる
http://www.iteye.com/topic/656670 http://www.iteye.com/topic/962172
public class CurrMap {
/** */
private static final Executor EXECUTOR = Executors.newFixedThreadPool(20);
/**
*
* @param args
*/
public static void main(String[] args) {
// final Map<String, String> map = new ConcurrentHashMap<String, String>();
final Map<String, String> map = new HashMap<String, String>();
map.put("laotu", "handsome");
final Random random = new Random();
while (true) {
EXECUTOR.execute(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException ex) {
System.err.println("t5 catch the InterruptedException...");
}
for (String key : map.keySet()) {
}
}
}
});
for (int i = 0; i < 100; i++) {
EXECUTOR.execute(new Runnable() {
public void run() {
for (int i = 0; i < 1000; i++) {
try {
TimeUnit.MILLISECONDS.sleep(1);
} catch (InterruptedException ex) {
System.err.println("t1 catch the InterruptedException...");
}
int key = random.nextInt(1000);
map.put(String.valueOf(key), String.valueOf(key));
}
}
});
}
}
}
}
実行結果:
Exception in thread "pool-1-thread-1" java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:793)
at java.util.HashMap$KeyIterator.next(HashMap.java:828)
at com.alipay.ctu.biz.intl.filters.CurrMap$1.run(CurrMap.java:52)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:695)
次の2つのシナリオを試します.
a.HashMapをConcurrentHashMapに交換して実行する.
b.HashMapを使用する、第1セグメントEXECUTORを注釈する.executeのコードを実行します.
結果は次のとおりです.
案aは間違いを報告しないに違いない.シナリオbはこの間違いを報告しないはずだが、この間違いを報告する可能性は極めて小さい.
適用シーン:
取引の支払いイベントが来て、イベントのタイプはHashMapで、私達はカードの情報、IP情報などに対して情報の補完を行う必要があって、スレッドプールを通じて同時に情報の補完を実行する過程の中で、各スレッドの内部でmapを実行しました.put(key,value)の操作により、高同時で異常javaが投げ出す可能性がある.util.ConcurrentModificationException.(出現確率が低い)
このときスレッドでmapが実行する場合.keySet()操作、map中のデータを遍歴すると、異常javaが発生する.util.ConcurrentModificationExceptionの確率が高いです.
HashMapを使用すると、スレッドが安全ではないことがわかりますが、どのような問題が発生する可能性がありますか?
a.putのデータが失われた.
b.removeのデータは消去されず、依然として存在する.
c.HashMap resizeによるパフォーマンスの問題.
d.getデータの場合、デッドサイクルが発生します.
ソリューション:
ConcurrentHashMapがおすすめです.
では、何が原因なのでしょうか.
以下の2つの文章を参照することができる
http://www.iteye.com/topic/656670 http://www.iteye.com/topic/962172