這樣使用是有問題的。
ConcurrentMap能夠保證每壹次調用(例如壹次putIfAbsent)都是原子操作,不受多線程影響,但並不保證多次調用之間也是原子操作。
以上實現的GetKeyBM方法中,ConcurrentMap的方法被調用了許多次,不同線程之間必然存在著競爭關系,導致最終結果不正確。
現在的目標是,將下面描述的這壹系列操作作為原子操作:
“對每個分出來的詞通過調用GetKeyBM方法,如果存在,則取出對應的編碼,如果不存在,則加入KeyTotal中,並且給予壹個編碼,就是KeyTotal中的變量數加壹”
最直觀的方法就是整塊同步:
synchronized?(KeyTotal)?{ Integer?value?=?KeyTotal.get(word); if?(value?==?null)?{value?=?KeyTotal.size()?+?1;
KeyTotal.put(word,?value);
}}
這樣,使用普通的map就可以了。
如果妳使用的是Java 8的話,ConcurrentMap有壹個類似的方法 computeIfAbsent 可以使用:
KeyTotal.computeIfAbsent(word,?k?->?KeyTotal.size()?+?1);這樣才能確保壹次原子操作。
computeIfAbsent方法的作用是,如果word鍵值不存在,則使用第二個參數來生成壹個值放入map中,等價於以下代碼,並且是原子操作:
?V?computeIfAbsent(K?key,?Function<?super?K,?extends?V>?mappingFunction): if?(map.get(key)?==?null)?{ V?newValue?=?mappingFunction.apply(key); if?(newValue?!=?null) return?map.putIfAbsent(key,?newValue); }正好與妳的目標是壹致的。