[英]Resolving Java thread visibility and concurrency error using Map compute
我使用 Java 8。我有一個事件處理程序,它以高速率(每秒 n 個)接受事件,當我收到這么多事件時,我想將它們刷新到存儲中(在這個簡化的示例中為 1000)
我在第 25 行是否有可見性錯誤myCache.get(event.getKey()).add(event.getBean());
? 我應該在handleEvent()
方法上同步嗎?
public class myClass extends MySimpleEventHanlder {
private Map<String, List<MyBean>> myCache;
private ScheduledExecutorService scheduler;
public void MyClass() {
myCache = new ConcurrentHashMap<String, List<MyBean>>();
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(() -> {
for (Iterator<Map.Entry<String, List<MyBean>>> it = myCache.entrySet().iterator(); it.hasNext();) {
Map.Entry<String, List<MyBean>> entry = it.next();
if (entry.getValue().size() >= 1000) {
it.remove();
//do some more processing , flush to storage
}
}
}, 0, 60, TimeUnit.SECONDS);
}
@Override
public void handleEvent(Event event) {
if (myCachetCache.containsKey(event.getKey())) {
myCache.get(event.getKey()).add(event.getBean());
}
else{
List<MyBean> beans = new ArrayList<MyBeans>();
beans.add(event.getBean());
myCache.put(event.key, beans);
}
}
}
您肯定有可見性問題:您在一個線程中將項目添加到 ArrayList 中,並在另一個線程中從該 ArrayList 讀取 size(),兩者之間沒有同步。
另一個問題是鍵可能會在調用myCache.containsKey
和myCache.get
之間被刪除。 這將導致 NullPointerException。 這可以通過使用計算來解決,它保證是原子的。
myCache.compute(event.getKey(), (key, value) -> {
if (value == null) {
value = new ArrayList<>();
}
value.add(event.getBean());
return value;
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.