我希望能够有条件地替换 ConcurrentHashMap 中的值。也就是说,给定:
公共(public)类 PriceTick {
最终字符串 instrumentId;
...
最后的长时间戳;
...
还有一个类(我们称之为 TickHolder),它拥有一个 ConcurrentHashMap(我们称之为 map)。
我希望能够实现一个有条件的 put 方法,这样如果没有键的条目,则插入新条目,但如果存在现有条目,则仅当新条目中的时间戳值时才插入新条目 PriceTick 大于现有的 。
对于老式的 HashMap 解决方案,TickHolder 将有一个 put 方法:
公共(public)无效添加(PriceTick 勾号){
同步( map ){
if ((map.get(tick.instrumentId) == null)
|| (tick.getTimestamp() > map.get(tick.instrumentId).getTimestamp()) )
map.put(tick.instrumentId, tick);
}
}
使用 ConcurrentHashMap,人们会想要放弃同步并使用一些原子方法,如替换,但这是无条件的。所以很明显必须写出“条件替换”方法。
然而,由于测试和替换操作是非原子的,为了线程安全,它必须是同步的——但是我对 ConcurrentHashMap 源的初步阅读让我认为外部同步和它们的内部锁不会工作得很好,所以至少,每个执行结构更改和包含类执行的 Map 方法都必须由包含类同步......即使那样,我也会相当不安。
我想过继承 ConcurrentHashMap,但这似乎是不可能的。它使用具有默认访问权限的内部 final 类 HashEntry,因此尽管 ConcurrentHashMap 不是 final,但它不可扩展。
这似乎意味着我必须回退到将 TickHolder 实现为包含老式 HashMap 以编写我的条件替换方法。
那么,问题是:我对上述内容是否正确?我是否(希望)错过了一些会导致不同结论的东西,无论是明显的还是微妙的?我真的很想能够在这里使用那个可爱的条纹锁定机制。
最佳答案
@cletus 解决方案为我解决几乎相同的问题奠定了基础。我认为需要进行一些更改,但好像 oldTick 为 null 然后 replace 会抛出一个 NullPointerException,如@hotzen 所述
PriceTick oldTick;
do {
oldTick = map.putIfAbsent(newTick.getInstrumentId());
} while (oldTick != null && oldTick.before(newTick) && !map.replace(newTick.getInstrumentId(), oldTick, newTick);
关于java - ConcurrentHashMap 条件替换,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1395010/