Guide pour CopyOnWriteArrayList

Guide de CopyOnWriteArrayList

1. Vue d'ensemble

Dans cet article rapide, nous allons examiner lesCopyOnWriteArrayList du packagejava.util.concurrent.

Ceci est une construction très utile dans les programmes multithreads - lorsque nous voulons effectuer une itération sur une liste de manière sécurisée pour les threads sans synchronisation explicite.

2. APICopyOnWriteArrayList

La conception duCopyOnWriteArrayList utilise une technique intéressante pour le rendre thread-safe sans nécessiter de synchronisation. Lorsque nous utilisons l'une des méthodes de modification - telles queadd() ouremove() –, tout le contenu desCopyOnWriteArrayList est copié dans la nouvelle copie interne.

En raison de ce simple fait,we can iterate over the list in a safe way, even when concurrent modification is happening.

Lorsque nous appelons la méthodeiterator() sur lesCopyOnWriteArrayList,, nous récupérons unIterator sauvegardé par l’instantané immuable du contenu desCopyOnWriteArrayList.

Son contenu est une copie exacte des données qui se trouvent dans unArrayList depuis le moment où leIterator a été créé. Même si, entre-temps, un autre thread ajoute ou supprime un élément de la liste, cette modification crée une nouvelle copie des données qui seront utilisées lors de toute recherche ultérieure dans cette liste.

Les caractéristiques de cette structure de données le rendent particulièrement utile dans les cas où nous itérons dessus plus souvent que nous ne le modifions. Si l'ajout d'éléments est une opération courante dans notre scénario, alorsCopyOnWriteArrayList ne sera pas un bon choix - car les copies supplémentaires conduiront certainement à des performances inférieures à la normale.

3. Itération surCopyOnWriteArrayList lors de l'insertion

Disons que nous créons une instance desCopyOnWriteArrayList qui stocke des entiers:

CopyOnWriteArrayList numbers
  = new CopyOnWriteArrayList<>(new Integer[]{1, 3, 5, 8});

Ensuite, nous voulons parcourir ce tableau, nous créons donc une instanceIterator:

Iterator iterator = numbers.iterator();

Après la création duIterator, nous ajoutons un nouvel élément à la listenumbers:

numbers.add(10);

Gardez à l'esprit que, lorsque nous créons un itérateur pour lesCopyOnWriteArrayList,, nous obtenons un instantané immuable des données de la liste au moment oùiterator() a été appelé.

Pour cette raison, en l'itérant, nous ne verrons pas le nombre10 dans l'itération:

List result = new LinkedList<>();
iterator.forEachRemaining(result::add);

assertThat(result).containsOnly(1, 3, 5, 8);

Une itération ultérieure utilisant desIterator nouvellement créés renverra également le numéro 10 qui a été ajouté:

Iterator iterator2 = numbers.iterator();
List result2 = new LinkedList<>();
iterator2.forEachRemaining(result2::add);

assertThat(result2).containsOnly(1, 3, 5, 8, 10);

4. La suppression pendant l'itération n'est pas autorisée

LeCopyOnWriteArrayList a été créé pour permettre la possibilité d'itérer en toute sécurité sur des éléments même lorsque la liste sous-jacente est modifiée.

En raison du mécanisme de copie, l'opérationremove() sur leIterator renvoyé n'est pas autorisée - résultant avecUnsupportedOperationException:

@Test(expected = UnsupportedOperationException.class)
public void whenIterateOverItAndTryToRemoveElement_thenShouldThrowException() {

    CopyOnWriteArrayList numbers
      = new CopyOnWriteArrayList<>(new Integer[]{1, 3, 5, 8});

    Iterator iterator = numbers.iterator();
    while (iterator.hasNext()) {
        iterator.remove();
    }
}

5. Conclusion

Dans ce rapide didacticiel, nous avons examiné l'implémentation deCopyOnWriteArrayList du packagejava.util.concurrent.

Nous avons vu la sémantique intéressante de cette liste et comment elle peut être itérée de manière sécurisée pour les threads, tandis que d'autres threads peuvent continuer à insérer ou à en supprimer des éléments.

L'implémentation de tous ces exemples et extraits de code peut être trouvée dans leGitHub project - il s'agit d'un projet Maven, il devrait donc être facile à importer et à exécuter tel quel.