Java:如何以原子方式替换Map中的所有值? [英] Java: How to atomically replace all values in a Map?

查看:349
本文介绍了Java:如何以原子方式替换Map中的所有值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在多线程环境中有一个有状态的bean,它将其状态保存在映射中。现在,我需要一种在一次原子操作中替换该映射的所有值的方法。

I have a stateful bean in an multi-threaded enviroment, which keeps its state in a map. Now I need a way to replace all values of that map in one atomic action.

public final class StatefulBean {

    private final Map<String, String> state = new ConcurrentSkipListMap<>();

    public StatefulBean() {
        //Initial state
        this.state.put("a", "a1");
        this.state.put("b", "b1");
        this.state.put("c", "c1");
    }

    public void updateState() {
        //Fake computation of new state
        final Map<String, String> newState = new HashMap<>();
        newState.put("b", "b1");
        newState.put("c", "c2");
        newState.put("d", "d1");

        atomicallyUpdateState(newState);
        /*Expected result
         *  a: removed
         *  b: unchanged
         *  C: replaced
         *  d: added*/
    }

    private void atomicallyUpdateState(final Map<String, String> newState) {
        //???
    }
}

目前我使用的是 ConcurrentSkipListMap 作为 ConcurrentMap 的实现,但这不是必需的。

At the moment I use ConcurrentSkipListMap as implementation of a ConcurrentMap, but that isn't a requirement.

我认为解决此问题的唯一方法是使全局状态 易失性,并完全替换地图或使用 AtomicReferenceFieldUpdater
有更好的方法吗?

The only way I see to solve this problem is to make the global state volatile and completely replace the map or use a AtomicReferenceFieldUpdater. Is there a better way?

我的更新非常频繁,每秒一次或两次,但是机会很少。整个地图也将永远只包含少于20个值。

My updates are quite frequent, once or twice a second, but chance only very few values. Also the whole map will only ever contain fewer than 20 values.

推荐答案

采用CAS和 AtomicReference 将是在每次批量更新时复制地图内容。

Approach with CAS and AtomicReference would be to copy map content on each bulk update.

AtomicReference<Map<String, String>> workingMapRef = new AtomicReference<>(new HashMap<>());

此映射可以是并发的,但对于批量更新它是只读的。然后在 updateState 中循环 doUpdateState(),直到得到true,这意味着您的值已更新。

This map can be concurrent, but for "bulk updates" it is read-only. Then in updateState looping doUpdateState() until you get true and that means that your values has been updated.

void updateState() {
    while (!doUpdateState());
}

boolean doUpdateState() {
    Map<String, String> workingMap = workingMapRef.get();
    //copy map content
    Map<String, String> newState = new HashMap<>(workingMap); //you can make it concurrent

    newState.put("b", "b1");
    newState.put("c", "c2");
    newState.put("d", "d1");

    return workingMapRef.compareAndSet(workingMap, newState);
}

这篇关于Java:如何以原子方式替换Map中的所有值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆