Me gustaría recopilar algunas métricas de varios lugares en una aplicación web. Para simplificar, todos estos serán contadores y, por lo tanto, la única operación modificadora es incrementarlos en 1.Contadores de incremento automático almacenados en ConcurrentHashMap
Los incrementos serán simultáneos y frecuentes. Las lecturas (volcar las estadísticas) es una operación rara.
Estaba pensando en utilizar un ConcurrentHashMap. El problema es cómo incrementar los contadores correctamente. Como el mapa no tiene una operación de "incremento", primero necesito leer el valor actual, incrementarlo en lugar de poner el nuevo valor en el mapa. Sin más código, esta no es una operación atómica.
¿Es posible lograr esto sin sincronización (lo que anularía el propósito del ConcurrentHashMap)? ¿Tengo que mirar Guava?
Gracias por cualquier apuntador.
P.S.
Hay una pregunta relacionada sobre SO (Most efficient way to increment a Map value in Java), pero centrado en el rendimiento y no multi-threading
ACTUALIZACIÓN
Para los que llegan aquí a través de búsquedas sobre el mismo tema: además de las respuestas a continuación, hay una utilidad presentation que incidentalmente cubre el mismo tema. Ver diapositivas 24-33.
Pero no se olvide de almacenar el 'HashMap' en una 'final' miembro. Y mejor envuelva el mapa en un contenedor 'no modificable'. Mejor aún, puedes usar 'ImmutableMap' de Guava (superconjunto de la colección de google) y debería ser realmente muy rápido. –
@Zwei: buen punto, editó la respuesta para incluir ese consejo :) –
La lista de métricas se construye a medida que suministran datos (es decir, las claves del mapa se agregarán a medida que el sistema se ejecuta y se golpean varios puntos de recolección; priori sería propenso a errores). Me olvidé del incremento de AtomicLongAndGet(), es justo lo que necesito. Si no existiera, estaba pensando que otro enfoque habría sido que los recopiladores de métricas no aumentaran los contadores, sino simplemente agregar la solicitud para hacerlo en una cola mantenida por el singleton. Por lo tanto, las personas que llaman solo agregan() a una lista, que periódicamente se lee y procesa. No es tan simple, sin embargo. – wishihadabettername