2016-07-31 131 views
0

這是一個有效的代碼來寫,如果我想避免不必要的包含調用?
我希望避免每次調用都包含調用,因爲這是對時間敏感的代碼。檢查putIfAbsent失敗

cancelretryCountMap.putIfAbsent(tag,new AtomicInteger(0)); 
count = cancelretryCountMap.get(tag).incrementAndGet(); 
if(count > 10){ 
    ///abort after x retries 
    .... 
} 

我使用JDK 7

回答

0

通常情況下,你可以使用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之中,要避免分配「開心」路徑中的默認值(即,當已經有給定鍵的條目時)。

如果沒有匹配的條目,你必須使用順序putIfAbsent返回值

之間
  • 該條目仍下落不明區分(默認值爲已添加由於呼叫)在這種情況下,該方法返回null
  • 其他線程已經贏得了比賽,並插入調用get後的新條目(在這種情況下,該方法返回與給定鍵關聯的當前值)

你可以抽象這個序列通過引入一個輔助方法,例如,

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,因此您必須自行開發,就像這裏所做的那樣。