ConcurrentHashMap統計單詞出現的次數
阿新 • • 發佈:2019-06-27
/** * 統計單詞出現的次數 * @author wucj * @date 2019-06-27 11:35 **/ public class WordsCount { private final HashMap<String,Long> wordCountHashMap = new HashMap<>(); private final ConcurrentHashMap<String,Long> wordCountConcurrentHashMap = new ConcurrentHashMap<>(); private final ConcurrentHashMap<String,AtomicLong> wordCountAtomicConcurrentHashMap = new ConcurrentHashMap<>(); /** * 多執行緒併發時會出現錯誤覆蓋 * @param word * @return */ public long increaseHm(String word){ Long oldCount = wordCountHashMap.get(word); long newCount = null==oldCount?0:oldCount+1; wordCountHashMap.put(word,newCount); return newCount; } /** * 執行效率可能偏低、佔用cpu過多 * @param word * @return */ public long increaseCasChm(String word){ Long oldValue; long newValue = 0; // 空轉也是很耗時的 while (true){ oldValue = wordCountConcurrentHashMap.get(word); if(null==oldValue){ newValue = 1; // 如果map中不存在值,則設定當前值,並且返回null // 如果map中存在值,則不設定當前值,並且返回原始值 if(wordCountConcurrentHashMap.putIfAbsent(word,newValue)==null){ break; } }else{ newValue = oldValue +1; if(wordCountConcurrentHashMap.replace(word,oldValue,newValue)){ break; } } } return newValue; } /** * 原子操作:上面的實現每次呼叫都會涉及Long物件的拆箱和裝箱操作,很明顯,更好的實現方式是採用AtomicLong * 缺點:如果多個執行緒同時增加一個目前還不存在的詞,那麼很可能會產生多個newNumber物件, * 但最終只有一個newNumber有用,其他的都會被扔掉。對於這個應用,這不算問題,建立AtomicLong的成本不高,而且只在新增不存在詞是出現。 * @param word * @return */ public long increaseAtomicLong(String word){ AtomicLong number = wordCountAtomicConcurrentHashMap.get(word); if(number==null){ AtomicLong newAtomicLong = new AtomicLong(0); number = wordCountAtomicConcurrentHashMap.putIfAbsent(word,newAtomicLong); if(null==number){ number = newAtomicLong; } } return number.incrementAndG