2016-07-31 10 views
0

Ist dies ein gültiger Code zu schreiben, wenn ich vermeiden möchte unnötige enthält?
Ich möchte vermeiden, enthält einen Aufruf bei jedem Aufruf, da dies sehr zeitkritischen Code ist.Überprüfen Sie den Ausfall von PutIfAbsent

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

Ich bin mit JDK 7

Antwort

0

Normalerweise würden Sie putIfAbsent wie folgt verwenden:

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(); 
    } 
} 

Der Grund für die explizite get Wesen, dass Sie die Zuordnung vermeiden möchten von der Standardwert im "Happy" -Pfad (dh wenn bereits ein Eintrag mit dem angegebenen Schlüssel vorhanden ist).

Wenn kein entsprechender Eintrag vorhanden ist, müssen Sie den Rückgabewert von putIfAbsent verwenden, um zwischen

  • der Eintrag noch vermisst wurde, zu unterscheiden (und der Standardwert ist aufgrund des Anruf hinzugefügt wurde), in diesem Fall das Verfahren kehrt null und
  • ein anderer Thread ist, das Rennen und eingefügt, um den neuen Eintrag nach dem Aufruf von get (in diesem Fall das Verfahren gibt den aktuellen Wert, die mit dem gegebenen Schlüssel)
gewonnen

Sie abstrahieren kann diese Sequenz durch eine Hilfsmethode einzuführen, zum Beispiel

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; 
     } 
    } 
} 

Sie dies in Ihrem Beispiel verwenden:

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 ... 
    } 
} 

Beachten Sie, dass dies tatsächlich bereits im JDK 8 vorgesehen ist als default Methode auf Map, aber da Sie noch auf JDK 7 sind, müssen Sie Ihre eigenen rollen, wie hier gemacht.