Last editor: Dave Cherry, last modified: Oct 25, 2009
java.util.concurrent.ConcurrentHashMap is an implementation of the java.util.concurrent.ConcurrentMap interface that is backed by a hashmap. This implementation can reduce thread contention by allowing more than one thread to read and write to the map at the same time. Read operations do not lock unless instability is suspected, IE. the get method is about to return null. Write operations will only lock the section of the map that contains the item being updated. Again, locks only affect one segment of the map - this applies to both read and write operations.
Notice the word section in the previous paragraph. This is a very important difference from a normal map that gives it an edge in terms of performance. Instead of having one lock that operates on the whole map, the table is split into segments, and each segment has a lock. This means that in the event that locking is required only one segment of the map gets locked.
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ConcurrentHashMap;
public class Concurrent
{
private ConcurrentMap<Integer, String> namesById;
private Concurrent()
{
// use the constructor to adjust the capacity, by default
// the load factor and concurrency level are usually OK.
final int CAPACITY = 100;
namesById = new ConcurrentHashMap<Integer, String>(CAPACITY);
}
private void changeNameForId(int id, String name)
{
// notice this is not synchronized
String lastValue = namesById.put(id, name);
}
private String findNameForUser(int id)
{
// notice this is not synchronized
return namesById.get(id);
}
}
Just like a normal hashmap, the default size of the ConcurrentHashMap is rather small. Infact the default hash table is only 16 locations. Should you expect many items to be stored in the map, set the intial capacity to be about twice the number of expected items as a general rule. If you do not do this hashmap will keep growing using load factor to determine when it is full.
ConcurrentHashMap allows you to tweak the number of segments by setting the concurrency level at construction, this is defined in terms of number of reader threads. I believe that the default implementation is correctly sized for many applications.