Iterator Fail-Safe vs Itterator Fail-Fast

Itérateur à sécurité intrinsèque vs itérateur à défaillance rapide

1. introduction

Dans cet article, nous présenterons le concept deIterators Fail-Fast et Fail-Safe.

Les systèmes Fail-Fast interrompent l'opération aussi vite que possible, exposant immédiatement les pannes et arrêtant l'ensemble de l'opération.

Alors que,Fail-Safe systems don’t abort an operation in the case of a failure. Such systems try to avoid raising failures as much as possible.

2. Échec rapideIterators

Les itérateurs rapides en Java ne fonctionnent pas lorsque la collection sous-jacente est modifiée.

Collections gère un compteur interne appelémodCount. Chaque fois qu'un élément est ajouté ou supprimé desCollection, ce compteur est incrémenté.

Lors de l'itération, à chaque appel denext(), la valeur actuelle demodCount est comparée à la valeur initiale. En cas de non-concordance, il renvoieConcurrentModificationException qui abandonne l'opération entière.

Itérateurs par défaut pourCollections à partir dejava.util package tels queArrayList,HashMap, etc. sont Fail-Fast.

ArrayList numbers = // ...

Iterator iterator = numbers.iterator();
while (iterator.hasNext()) {
    Integer number = iterator.next();
    numbers.add(50);
}

Dans l'extrait de code ci-dessus, lesConcurrentModificationException sont lancés au début d'un cycle d'itération suivant une fois la modification effectuée.

Le comportement Fail-Fast n'est pas garanti dans tous les scénarios car il est impossible de prédire le comportement en cas de modifications simultanées. These iterators throw ConcurrentModificationException on a best effort basis.

Si pendant l'itération sur unCollection,an item is removed using Iterator‘s remove() method, that’s entirely safe and doesn’t throw an exception.

Cependant, si la méthoderemove() deCollection est utilisée pour supprimer un élément, elle lève une exception:

ArrayList numbers = // ...

Iterator iterator = numbers.iterator();
while (iterator.hasNext()) {
    if (iterator.next() == 30) {
        iterator.remove(); // ok!
    }
}

iterator = numbers.iterator();
while (iterator.hasNext()) {
    if (iterator.next() == 40) {
        numbers.remove(2); // exception
    }
}

3. Itérateurs à sécurité intégrée

Les itérateurs Fail-Safe favorisent l’absence de pannes plutôt que les inconvénients de la gestion des exceptions.

Ces itérateurs créent un clone desCollection réels et effectuent une itération dessus. Si une modification survient après la création de l'itérateur, la copie reste intacte. Par conséquent, cesIterators continuent de boucler sur lesCollection même s'ils sont modifiés.

Cependant, il est important de se rappeler qu’il n’existe pas de véritable itérateur à sécurité intégrée. Le terme correct est faiblement cohérent.

Cela signifie,if aCollection is modified while being iterated over, what the Iterator sees is weakly guaranteed. Ce comportement peut être différent pour différentsCollections et est documenté dans les Javadocs de chacun de cesCollection.

LesIteratorsFail-Safe présentent cependant quelques inconvénients. Un inconvénient est que lesIterator isn’t guaranteed to return updated data from the Collection, car ils fonctionnent sur le clone au lieu desCollection réels.

Un autre inconvénient est la surcharge de création d'une copie desCollection, à la fois en termes de temps et de mémoire.

Iterators surCollections du packagejava.util.concurrent tel queConcurrentHashMap,CopyOnWriteArrayList, etc. sont de nature à sécurité intégrée.

ConcurrentHashMap map = new ConcurrentHashMap<>();

map.put("First", 10);
map.put("Second", 20);
map.put("Third", 30);
map.put("Fourth", 40);

Iterator iterator = map.keySet().iterator();

while (iterator.hasNext()) {
    String key = iterator.next();
    map.put("Fifth", 50);
}

Dans l'extrait de code ci-dessus, nous utilisons Fail-SafeIterator. Par conséquent, même si un nouvel élément est ajouté auxCollection lors de l'itération, il ne lève pas d'exception.

L'itérateur par défaut_ for the _ConcurrentHashMap est faiblement cohérent. Cela signifie que ceIterator peut tolérer des modifications concurrentes, traverse les éléments tels qu'ils existaient lorsqueIterator a été construit et peut (mais n'est pas garanti) refléter les modifications apportées auxCollection après la construction de lesIterator.

Par conséquent, dans l'extrait de code ci-dessus, l'itération boucle cinq fois, ce qui signifieit does detect the newly added element to the Collection.

4. Conclusion

Dans ce didacticiel, nous avons vu ce que signifient Fail-Safe et Fail-FastIteratorset comment ils sont implémentés en Java.

Le code complet présenté dans cet article est disponibleover on GitHub.