当前位置: 首页 > 面试题库 >

Java:如何以原子方式替换Map中的所有值?

汪晟睿
2023-03-14
问题内容

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

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,但这不是必需的。

我认为解决此问题的唯一方法是制作全局state
volatile地图并完全替换地图或使用AtomicReferenceFieldUpdater。有没有更好的办法?

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


问题答案:

使用CAS的方法AtomicReference是在每次批量更新时复制地图内容。

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

该映射可以是并发的,但是对于“批量更新”它是只读的。然后updateState循环执行doUpdateState()直到得到正确的结果,这意味着您的值已更新。

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);
}


 类似资料:
  • 我正在尝试用大量新值替换所有文档。 例如,我们在数据库中500k文档,并且我们500k了相同的文档,其中包含更新的道具。现在我们需要更新旧数据。 想法是在新集合中使用InsertMany with lean选项,然后删除旧集合以减少读/写次数。 问题是,对于这种情况,有没有更简单的方法? 在这种情况下,也许连进出口都更好? PS模型。updateMany()有一个过滤器,我们这里不需要过滤器,因为

  • 问题内容: 我的文字可能具有不同的换行样式。我想将所有换行符’\ r \ n’,’\ n’,’\ r’替换为同一换行符(在本例中为\ r \ n)。 最快的方法是什么?我当前的解决方案如下所示: 问题是您无法一次替换,因为\ r \ n将被复制到\ r \ n \ r \ n。 感谢您的帮助! 问题答案: 如果您不想替换所有Unicode换行符,而是仅替换CRLF样式的换行符,请使用: 匹配这些换

  • 问题内容: 我想用字符替换Java字符串中的所有字符。因此,无论它是什么字符都无关紧要,应将其替换为。 我知道互联网上有很多例子,但是没有一个例子可以代替每个角色,我已经尽力了,但没有成功。 问题答案: Java 11及更高版本 注: 这将替换换行符用。如果要保留,请参见下面的解决方案。 Java 10及更早版本 这样可以 保留 换行符。 要在Java 10和更早的版本中也用换行符替换,可以使用:

  • 我在pyspark中有一个超过300列的数据帧。在这些列中,有些列的值为null。 例如: 当我想对列u 1求和时,结果得到的是Null,而不是724。 现在,我想用空格替换数据框所有列中的null。因此,当我尝试对这些列求和时,我不会得到null值,但会得到一个数值。 我们如何在pyspark中实现这一点

  • 上下文 我继承了一个基于Spring的小项目——它跟踪服务器、软件安装等,供团队内部使用。它使用角度前端和Spring/java/mysql后端作为restful后端。 在过去的几个月里,我把它换成了Spring boot。我不熟悉Spring和Spring boot。所以我一边学习。 我开始用JPA("spring-data-rest")替换"手工编码"sql。JPA对于某些表来说很容易,但对于

  • 请看下面的代码: 当我运行时,我得到以下异常: 线程“主”java.util.regex.PatternSyntaxException异常:指数4附近无与伦比的收盘“)” 0.3港元)预订:virginiawong@fahkco.com.hk4)FCR 根据我的理解,我必须对参数'(',')'进行转义,我试图这样做(看看代码中的注释部分)没有任何异常,但是我添加到字符串的换行符似乎没有出现。