ConcurrentHashMap统计单词出现的次数

原创
2019/06/27 15:10
阅读数 782
/**
 * 统计单词出现的次数
 * @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.incrementAndGet();
    }


}
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部