2016-07-31 9 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, вам нужно катиться самостоятельно, как это делается здесь.