Java 从ConcurrentMap.remove()获取密钥是否存在
在Java中,有,这返回以下之一:Java 从ConcurrentMap.remove()获取密钥是否存在,java,concurrency,thread-safety,concurrenthashmap,Java,Concurrency,Thread Safety,Concurrenthashmap,在Java中,有,这返回以下之一: 预期值已存在,并且已被删除 预期值不存在,因此尚未删除 但我想得到的是: 预期值已存在,并且已被删除 该键下有一个值,但不是预期值,因此尚未删除该值 该键下没有值,因此尚未删除 如何以并发和线程安全的方式获取此信息 这就是我试图保护的代码 // attempt to remove the old session... if (!sessions.remove(player.getId(), existing)) { // it was not r
- 预期值已存在,并且已被删除
- 预期值不存在,因此尚未删除
这就是我试图保护的代码
// attempt to remove the old session...
if (!sessions.remove(player.getId(), existing)) {
// it was not removed...
if (sessions.containsKey(player.getId())) { // TODO threadsafe
// ...because in the meantime some other thread logged in as that user
throw new ServiceError(LobbyService.ERR_LOGIN_INVALID, Maps.create("reason", "already-logged-in"));
} else {
// ...because it was no longer there, which is as it should be
}
} else {
// it was removed, which is bad, because it shouldn't have been there still
log.warn("Kicking old session of " + player.getId() + " failed");
}
或概括:
if (!sessions.remove(key, expected)) {
if (sessions.containsKey(key)) { // TODO threadsafe
// 2
} else {
// 3
}
} else {
// 1
}
我不明白你在医生身上看到的和你想要的。所以请让我写下来
- 键
与值A
关联B
将返回true和remove-mapping A->B(这是您想要的)remove(A,B)
- 键
与值A
关联C
将返回remove(A,B)
,映射A->C将不会被删除(这是您想要的)false
- 键
与无值关联A
将返回remove(A,null)
(这是您想要的)false
换言之,似乎移除正是你想要的。。。或者,您的代码中可能存在另一个bug。您可以使用原子引用来提供帮助。假设您使用非空原子引用进行前置,您可以尝试在会话中使用引用的当前值为
existing
的谓词使该值为空。如果是,则从映射中“删除”,否则AtomicReference的当前值就是当前存在的值
AtomicReference<Session> ref = session.get(player.getId());
if (ref.compareAndSet(existing,null) {
//1
}else{
Session current = ref.get();
if(current != null){
//2
}else{
//3
}
}
AtomicReference=session.get(player.getId());
if(参考比较数据集(现有,空){
//1
}否则{
会话当前=ref.get();
如果(当前!=null){
//2
}否则{
//3
}
}
此代码似乎几乎提供了您所要求的内容,但我不确定它是否满足了您的要求
你能详细谈谈你到底想做什么吗
class Player {};
ConcurrentMap<String,Player> players = new ConcurrentHashMap();
void playerIDChanged(String id, Player oldPlayer, Player newPlayer) {
Player old = players.replace(id, newPlayer);
if ( old == oldPlayer ) {
// The expected value was there and has been REPLACED.
} else {
if ( old == null ) {
// There is no value under that key, so it has not been removed.
} else {
// There is a value under that key, but not the expected one, so it HAS been replaced.
// NB: This is slightly different from what you are asking for.
}
}
}
class播放器{};
ConcurrentMap players=新的ConcurrentHashMap();
无效玩家id已更改(字符串id、玩家oldPlayer、玩家newPlayer){
Player old=players.replace(id,newPlayer);
if(old==oldPlayer){
//预期值已存在,并已被替换。
}否则{
if(old==null){
//该键下没有值,因此尚未删除。
}否则{
//该键下有一个值,但不是预期的值,因此它已被替换。
//注意:这与你的要求略有不同。
}
}
}
不应该是sessions.remove(player.getId(),existing)
而不是sessions.remove(sessions,existing)
?您能描述一下如何使用该映射的总体情况吗?您准确地描述了我的问题,后两种情况都不能从映射中删除条目(这是我想要的)它们还返回相同的结果,false
,这是不够的信息,因为我需要在后面的代码中区分这两种情况。