检查 putIfAbsent 失败
Check failure of putIfAbsent
如果我想避免不必要的 contains 调用,这是一个有效的代码吗?
我希望避免在每次调用时都调用 contains,因为这是对时间高度敏感的代码。
cancelretryCountMap.putIfAbsent(tag,new AtomicInteger(0));
count = cancelretryCountMap.get(tag).incrementAndGet();
if(count > 10){
///abort after x retries
....
}
我正在使用 JDK 7
通常,您会像这样使用 putIfAbsent
:
final AtomicInteger present = map.get(tag);
int count;
if (present != null) {
count = present.incrementAndGet();
} else {
final AtomicInteger instance = new AtomicInteger(0);
final AtomicInteger marker = map.putIfAbsent(tag, instance);
if (marker == null) {
count = instance.incrementAndGet();
} else {
count = marker.incrementAndGet();
}
}
显式 get
的原因是,您想避免在 "happy" 路径中分配默认值(即,当已经存在具有给定键的条目时) .
如果没有匹配的条目,则必须使用putIfAbsent
的return值来区分
- 该条目仍然缺失(并且由于调用而添加了默认值),在这种情况下,方法 returns
null
和
- 一些其他线程赢得了比赛并在调用
get
之后插入了新条目(在这种情况下,方法 returns 是与给定键关联的当前值)
你可以通过引入辅助方法来抽象这个序列,例如
interface Supplier<T> {
T get();
}
static <T> T computeIfAbsent(ConcurrentMap<K,T> map, T key, Supplier<? extends T> producer) {
final T present = map.get(key);
if (present != null) {
return present;
} else {
final T fallback = producer.get();
final T marker = map.putIfAbsent(key, fallback);
if (marker == null) {
return fallback;
} else {
return marker;
}
}
}
你可以在你的例子中使用这个:
static final Supplier<AtomicInteger> newAtomicInteger = new Supplier<AtomicInteger>() {
public AtomicInteger get() { return new AtomicInteger(0); }
};
void yourMethodWhatever(Object tag) {
final AtomicInteger counter = computeIfAbsent(cancelretryCountMap, tag, newAtomicInteger);
if (counter.incrementAndGet() > 10) {
... whatever ...
}
}
请注意,这实际上已经在 JDK 8 中作为 default
方法在 Map
中提供,但由于您仍在使用 JDK 7,因此您有自己滚动,就像这里所做的那样。
如果我想避免不必要的 contains 调用,这是一个有效的代码吗?
我希望避免在每次调用时都调用 contains,因为这是对时间高度敏感的代码。
cancelretryCountMap.putIfAbsent(tag,new AtomicInteger(0));
count = cancelretryCountMap.get(tag).incrementAndGet();
if(count > 10){
///abort after x retries
....
}
我正在使用 JDK 7
通常,您会像这样使用 putIfAbsent
:
final AtomicInteger present = map.get(tag);
int count;
if (present != null) {
count = present.incrementAndGet();
} else {
final AtomicInteger instance = new AtomicInteger(0);
final AtomicInteger marker = map.putIfAbsent(tag, instance);
if (marker == null) {
count = instance.incrementAndGet();
} else {
count = marker.incrementAndGet();
}
}
显式 get
的原因是,您想避免在 "happy" 路径中分配默认值(即,当已经存在具有给定键的条目时) .
如果没有匹配的条目,则必须使用putIfAbsent
的return值来区分
- 该条目仍然缺失(并且由于调用而添加了默认值),在这种情况下,方法 returns
null
和 - 一些其他线程赢得了比赛并在调用
get
之后插入了新条目(在这种情况下,方法 returns 是与给定键关联的当前值)
你可以通过引入辅助方法来抽象这个序列,例如
interface Supplier<T> {
T get();
}
static <T> T computeIfAbsent(ConcurrentMap<K,T> map, T key, Supplier<? extends T> producer) {
final T present = map.get(key);
if (present != null) {
return present;
} else {
final T fallback = producer.get();
final T marker = map.putIfAbsent(key, fallback);
if (marker == null) {
return fallback;
} else {
return marker;
}
}
}
你可以在你的例子中使用这个:
static final Supplier<AtomicInteger> newAtomicInteger = new Supplier<AtomicInteger>() {
public AtomicInteger get() { return new AtomicInteger(0); }
};
void yourMethodWhatever(Object tag) {
final AtomicInteger counter = computeIfAbsent(cancelretryCountMap, tag, newAtomicInteger);
if (counter.incrementAndGet() > 10) {
... whatever ...
}
}
请注意,这实际上已经在 JDK 8 中作为 default
方法在 Map
中提供,但由于您仍在使用 JDK 7,因此您有自己滚动,就像这里所做的那样。