Java:如何以原子方式替换Map中的所有值? [英] Java: How to atomically replace all values in a 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屋!