Concorrenza Java - Interfaccia ConcurrentMap

Un'interfaccia java.util.concurrent.ConcurrentMap è una sottointerfaccia dell'interfaccia Map, supporta operazioni atomiche sulla variabile mappa sottostante. Ha metodi get e set che funzionano come letture e scritture su variabili volatili. Cioè, un insieme ha una relazione accade prima con qualsiasi successivo get sulla stessa variabile. Questa interfaccia garantisce la sicurezza dei thread e le garanzie di atomicità.

Metodi ConcurrentMap

Sr.No. Metodo e descrizione
1

default V compute(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

Tenta di calcolare una mappatura per la chiave specificata e il suo valore mappato corrente (o null se non esiste una mappatura corrente).

2

default V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)

Se la chiave specificata non è già associata a un valore (o è mappata su null), tenta di calcolarne il valore utilizzando la funzione di mappatura data e la inserisce in questa mappa a meno che null.

3

default V computeIfPresent(K key, BiFunction<? super K,? super V,? extends V> remappingFunction)

Se il valore per la chiave specificata è presente e non nullo, tenta di calcolare una nuova mappatura data la chiave e il suo valore mappato corrente.

4

default void forEach(BiConsumer<? super K,? super V> action)

Esegue l'azione data per ciascuna voce in questa mappa fino a quando tutte le voci non sono state elaborate o l'azione genera un'eccezione.

5

default V getOrDefault(Object key, V defaultValue)

Restituisce il valore a cui è mappata la chiave specificata o defaultValue se questa mappa non contiene alcuna mappatura per la chiave.

6

default V merge(K key, V value, BiFunction<? super V,? super V,? extends V> remappingFunction)

Se la chiave specificata non è già associata a un valore o è associata a null, la associa al valore non null specificato.

7

V putIfAbsent(K key, V value)

Se la chiave specificata non è già associata a un valore, associarla al valore dato.

8

boolean remove(Object key, Object value)

Rimuove la voce per una chiave solo se attualmente mappata a un determinato valore.

9

V replace(K key, V value)

Sostituisce la voce per una chiave solo se attualmente mappata su un valore.

10

boolean replace(K key, V oldValue, V newValue)

Sostituisce la voce per una chiave solo se attualmente mappata a un determinato valore.

11

default void replaceAll(BiFunction<? super K,? super V,? extends V> function)

Sostituisce il valore di ogni voce con il risultato del richiamo della funzione data su quella voce finché tutte le voci non sono state elaborate o la funzione genera un'eccezione.

Esempio

Il seguente programma TestThread mostra l'utilizzo di ConcurrentMap rispetto a HashMap.

import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class TestThread {

   public static void main(final String[] arguments) {
      Map<String,String> map = new ConcurrentHashMap<String, String>();

      map.put("1", "One");
      map.put("2", "Two");
      map.put("3", "Three");
      map.put("5", "Five");
      map.put("6", "Six");

      System.out.println("Initial ConcurrentHashMap: " + map);
      Iterator<String> iterator = map.keySet().iterator();

      try { 
         
         while(iterator.hasNext()) {
            String key = iterator.next();
            
            if(key.equals("3")) {
               map.put("4", "Four");
            }
         }
      } catch(ConcurrentModificationException cme) {
         cme.printStackTrace();
      }
      System.out.println("ConcurrentHashMap after modification: " + map);

      map = new HashMap<String, String>();

      map.put("1", "One");
      map.put("2", "Two");
      map.put("3", "Three");
      map.put("5", "Five");
      map.put("6", "Six");

      System.out.println("Initial HashMap: " + map);
      iterator = map.keySet().iterator();

      try {
         
         while(iterator.hasNext()) {
            String key = iterator.next();
            
            if(key.equals("3")) {
               map.put("4", "Four");
            }
         }
         System.out.println("HashMap after modification: " + map);
      } catch(ConcurrentModificationException cme) {
         cme.printStackTrace();
      }
   }  
}

Questo produrrà il seguente risultato.

Produzione

Initial ConcurrentHashMap: {1 = One, 2 = Two, 3 = Three, 5 = Five, 6 = Six}
ConcurrentHashMap after modification: {1 = One, 2 = Two, 3 = Three, 4 = Four, 5 = Five, 6 = Six}
Initial HashMap: {1 = One, 2 = Two, 3 = Three, 5 = Five, 6 = Six}
java.util.ConcurrentModificationException
	at java.util.HashMap$HashIterator.nextNode(Unknown Source)
	at java.util.HashMap$KeyIterator.next(Unknown Source)
	at TestThread.main(TestThread.java:48)