我有 N 个添加值的线程和一个删除线程。我正在考虑如何同步添加到现有值列表和删除列表的最佳方法。
我猜下面的情况是可能的:
thread 1 checked condition containsKey, and entered in else block
thread 2 removed the value
thread 1 try to add value to existing list, and get returns null
我认为我可以使用的唯一方法是按映射值同步,在我们的例子中是添加和删除时的列表
private ConcurrentSkipListMap<LocalDateTime, List<Task>> tasks = new ConcurrentSkipListMap<>();
//Thread1,3...N
public void add(LocalDateTime time, Task task) {
if (!tasks.containsKey(time)) {
tasks.computeIfAbsent(time, k -> createValue(task));
} else {
//potentially should be synced
tasks.get(time).add(task);
}
}
private List<Task> createValue(Task val) {
return new ArrayList<>(Arrays.asList(val));
}
//thread 2
public void remove()
while(true){
Map.Entry<LocalDateTime, List<Task>> keyVal = tasks.firstEntry();
if (isSomeCondition(keyVal)) {
tasks.remove(keyVal.getKey());
for (Task t : keyVal.getValue()) {
//do task processing
}
}
}
}
最佳答案
关于 add
部分,您会真的倾向于使用 merge
,但是文档对此非常清楚 - 说它是不保证原子发生。
我会用 merge
替换您的 add
,但是处于锁定状态。
SomeLock lock ...
public void add(LocalDateTime time, Task task) {
lock.lock();
tasks.merge...
lock.unlock();
}
remove
方法也是如此。但是,如果您在锁定状态下做事,则首先不需要 ConcurrentSkipListMap
。
另一方面,如果您可以更改为 ConcurrentHashMap
- 它具有例如原子性的 merge
。
关于java - ConcurrentSkipListMap 如何使删除和添加调用原子化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46308086/