Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Map of AtomicInteger

I want to implement a shared object for calculation of statistics of executions of operations. Objects state will be represented by Map<String,AtomicInteger>(key is the name of operation, value is the number of times the operation was executed). Am I correct that I can choose a HashMap<String,AtomicInteger> implementation and use no synchronization on it for getting values from it since AtomicInteger has a volatile value field underneath it.

Sample of code that does addition and incrementation of execution stats:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public final class Stats {

private final Map<String, AtomicInteger> statistics = new HashMap<String, AtomicInteger>();

public int increment(String operationName) {
    if (!statistics.containsKey(operationName)) {
        synchronized (statistics) {
            if (!statistics.containsKey(operationName)) 
                statistics.put(operationName, new AtomicInteger(0));
        }
    }

    return statistics.get(operationName).getAndIncrement();
}

public int getOpStats(String operationName) {
    if (!statistics.containsKey(operationName)) {
        return 0;
    }
    return statistics.get(operationName).get();
}

}
like image 585
breedish Avatar asked Jan 19 '14 21:01

breedish


People also ask

Is AtomicInteger thread safe?

Atomic Objects It's also possible to achieve thread-safety using the set of atomic classes that Java provides, including AtomicInteger, AtomicLong, AtomicBoolean and AtomicReference. Atomic classes allow us to perform atomic operations, which are thread-safe, without using synchronization.

What is the use of AtomicInteger?

An AtomicInteger is used in applications such as atomically incremented counters, and cannot be used as a replacement for an Integer . However, this class does extend Number to allow uniform access by tools and utilities that deal with numerically-based classes.

How do you declare AtomicInteger?

AtomicInteger atomicInteger = new AtomicInteger(); This example creates an AtomicInteger with the initial value 0 . If you want to create an AtomicInteger with an initial value, you can do so like this: AtomicInteger atomicInteger = new AtomicInteger(123);

Is AtomicInteger synchronized?

Yes, you are correct. AtomicInteger would not grant any benefit if all access to the object is synchronized (only one thread, at most, would be accessing its contents at any given moment).


1 Answers

If you want to be thread safe with regards to counter initialization you should use a ConcurrentHashMap and always instanciate-and-increase the counters this way:

themap.putIfAbsent("the name", new AtomicInteger(0)); 
themap.get("the name").incrementAndGet();

You could also make sure you initialize all the counters used before you start, and just use whatever collection you like. A plain AtomicInteger[]-array is by far quickest, given that you know where to look, HashTable could be slightly quicker than HashMap.

If you know on beforehand which counters you have, you could also define a java enum of all the counter names and use an EnumMap<YourCountersEnum, AtomicInteger>. This would probably give look-up performance close to an AtomicInteger[]-array lookup.

like image 131
claj Avatar answered Sep 19 '22 23:09

claj