簡體   English   中英

使用 Map 計算解決 Java 線程可見性和並發錯誤

[英]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.containsKeymyCache.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM