HashMap vs. ConcurrentHashMap vs. SynchronizedMap: cómo se puede sincronizar un HashMap en Java

Publicado: 2015-01-29

Crunchify ConcurrentHashMap vs. Ejemplo de mapa sincronizado HashMap es una estructura de datos muy poderosa en Java. Lo usamos todos los días y en casi todas las aplicaciones. Hay bastantes ejemplos que he escrito antes sobre Cómo implementar el caché Threadsafe, ¿Cómo convertir Hashmap a Arraylist?

Usamos Hashmap en los dos ejemplos anteriores, pero esos son casos de uso bastante simples de Hashmap. HashMap is a non-synchronized .

¿Tiene alguna de las siguientes preguntas?

  • ¿Cuál es la diferencia entre ConcurrentHashMap y Collections.synchronizedMap(Map)?
  • ¿Cuál es la diferencia entre ConcurrentHashMap y Collections.synchronizedMap(Map) en términos de rendimiento?
  • ConcurrentHashMap vs Collections.synchronizedMap()
  • Preguntas de entrevista populares de HashMap y ConcurrentHashMap

En este tutorial repasaremos todas las consultas anteriores y por why and how podríamos sincronizar Hashmap.

¿Por qué?

El objeto Map es un contenedor asociativo que almacena elementos, formado por una combinación de una key de identificación única y un value mapeado. Si tiene una aplicación muy concurrente en la que puede querer modificar o leer el valor clave en diferentes subprocesos, entonces es ideal usar Hashmap concurrente. El mejor ejemplo es Producer Consumer, que maneja la lectura/escritura simultánea.

Entonces, ¿qué significa el mapa seguro para subprocesos? Si multiple threads acceden a un mapa hash al mismo tiempo y al menos uno de los subprocesos modifica el mapa estructuralmente, must be synchronized externally para evitar una vista inconsistente de los contenidos.

¿Cómo?

Hay dos formas en que podríamos sincronizar HashMap

  1. Método Java CollectionssynchronedMap()
  2. Usar ConcurrentHashMap

ConcurrentHashMapConcurrentHashMap

  • Debe usar ConcurrentHashMap cuando necesite una simultaneidad muy alta en su proyecto.
  • Es seguro para subprocesos sin sincronizar whole map .
  • Las lecturas pueden ocurrir muy rápido mientras que la escritura se realiza con un bloqueo.
  • No hay bloqueo a nivel de objeto.
  • El bloqueo tiene una granularidad mucho más fina a nivel de cubo de hashmap.
  • ConcurrentHashMap no lanza una ConcurrentModificationException si un subproceso intenta modificarlo mientras otro está iterando sobre él.
  • ConcurrentHashMap utiliza multitud de bloqueos.

SynchronizedHashMap

  • Sincronización a nivel de Objeto.
  • Cada operación de lectura/escritura necesita adquirir un bloqueo.
  • Bloquear toda la colección es una sobrecarga de rendimiento.
  • Básicamente, esto da acceso a un solo hilo a todo el mapa y bloquea todos los demás hilos.
  • Puede causar contención.
  • SynchronizedHashMap devuelve Iterator , que falla rápidamente en la modificación simultánea.

Ahora echemos un vistazo al código.

  1. Crear clase CrunchifyConcurrentHashMapVsSynchronizedHashMap.java
  2. Crear objeto para cada HashTable, SynchronizedMap y CrunchifyConcurrentHashMap
  3. Agregue y recupere 500k entradas del Mapa
  4. Mida el tiempo de inicio y finalización y muestre el tiempo en milisegundos
  5. Usaremos ExecutorService para ejecutar 5 threads en paralelo

Aquí hay un código Java:

  • shutdown() significa que el servicio ejecutor no toma más tareas entrantes.
  • awaitTermination() se invoca después de una solicitud de apagado.

Y, por lo tanto, primero debe apagar el serviceExecutor y luego bloquear y esperar a que finalicen los subprocesos.

Resultado de la consola de Eclipse: