Co to są niezawodne i odporne na awarie Iteratory w Javie


101

W Javie istnieją dwa typy iteratorów: odporne na awarie i szybkie.

Co to oznacza i czy jest między nimi różnica?


3
najlepszy link, jaki znalazłem javahungry.blogspot.com/2014/04/…
Premraj

2
Należy zauważyć, że specyfikacje Java SE nie używają terminu „fail-safe” do opisu jakichkolwiek iteratorów. Dlatego zalecam unikanie tego terminu. Zobacz także stackoverflow.com/a/38341921/1441122
Stuart Marks,

Odpowiedzi:


84

Jaka jest różnica między nimi ...

„Bezawaryjny” ( w inżynierii ) oznacza, że ​​coś zawodzi w sposób, który nie powoduje żadnych szkód lub jest ich minimalny. Ściśle mówiąc, w Javie nie ma czegoś takiego jak iterator odporny na awarie. Jeśli iterator zawiedzie (w normalnym znaczeniu „niepowodzenie”), można spodziewać się uszkodzenia.

Podejrzewam, że w rzeczywistości masz na myśli „słabo spójne” iteratory. Javadoc mówi:

„Większość współbieżnych implementacji kolekcji (w tym większość kolejek) również różni się od zwykłych konwencji java.util tym, że ich Iteratory i Spliteratory zapewniają słabo spójne, a nie szybkie przechodzenie po awarii”.

Zwykle słaba spójność oznacza, że ​​jeśli kolekcja jest modyfikowana jednocześnie z iteracją, gwarancje tego, co widzi iteracja, są słabsze. (Szczegóły zostaną określone w każdej z równoległych klas kolekcji javadocs).

„Odporność na awarię ” ( w projektowaniu systemów ) oznacza, że ​​stan awarii jest sprawdzany agresywnie, tak aby stan awarii był (tam, gdzie to możliwe 1 ) wykrywany, zanim możliwe będzie spowodowanie zbyt dużego uszkodzenia. W Javie iterator działający bezawaryjnie zawodzi, rzucając plik ConcurrentModificationException.

Alternatywa dla „szybkich niepowodzeń” i „słabo spójnych” jest semantyczna, gdy iteracja kończy się niepowodzeniem w nieprzewidywalny sposób; np. aby czasami udzielić złej odpowiedzi lub rzucić nieoczekiwany wyjątek. (Tak było w przypadku niektórych standardowych implementacji Enumerationinterfejsu API we wczesnych wersjach języka Java).

... i czy różnią się od iteratora, którego używamy do zbierania.

Nie. To są właściwości iteratorów implementowanych przez standardowe typy kolekcji; tzn. są albo „szybko nieudane”, albo „słabo spójne”… jeśli są używane poprawnie w odniesieniu do synchronizacji i modelu pamięci Java 1 .


Iteratory odporne na awarie są zwykle implementowane przy użyciu volatilelicznika w obiekcie kolekcji.

  • Gdy kolekcja jest aktualizowana, licznik jest zwiększany.
  • Po Iteratorutworzeniu aktualna wartość licznika jest osadzana w Iteratorobiekcie.
  • Podczas wykonywania Iteratoroperacji metoda porównuje dwie wartości liczników i zgłasza CME, jeśli są różne.

Z drugiej strony, słabo spójne iteratory są zwykle lekkie i wykorzystują właściwości wewnętrznych struktur danych każdej współbieżnej kolekcji. Nie ma ogólnego wzoru. Jeśli jesteś zainteresowany, przeczytaj kod źródłowy dla różnych klas kolekcji.


1 - Kierowca jest taki, że zachowanie bezawaryjne zakłada, że ​​aplikacja jest poprawnie identyfikowana w odniesieniu do synchronizacji i modelu pamięci. Oznacza to, że (na przykład) jeśli wykonasz iterację ArrayListbez prawidłowej synchronizacji, wynikiem może być uszkodzony wynik listy. Mechanizm „szybkiego niepowodzenia” prawdopodobnie wykryje równoczesną modyfikację (chociaż nie jest to gwarantowane), ale nie wykryje podstawowego uszkodzenia. Na przykład javadoc for Vector.iterator()mówi tak:

„Fail-fast zachowanie iterator nie może być zagwarantowane, jak to jest, ogólnie rzecz biorąc, niemożliwe, aby jakiekolwiek twarde gwarancje w obecności rozsynchronizowany jednoczesnej modyfikacji. Fail-fast iteratory rzucać ConcurrentModificationExceptionna zasadzie best-effort. Dlatego byłoby źle napisać program, który zależał od tego wyjątku ze względu na jego poprawność: szybkie działanie iteratorów w przypadku awarii powinno być używane tylko do wykrywania błędów. "


Może trochę nieistotne, ale może też uzupełniać to pytanie. A co ze stylem migawki używanym na przykład przez CoW? Mówiąc dokładniej, nie do końca rozumiem, w jaki sposób podstawowa tablica (lub migawka), którą iterator CoW iteruje po „nigdy”, widzi zmiany wprowadzane przez inne wątki, ponieważ nadal jesteśmy w stanie wywołać setArraykażdą modyfikację.
wyjście

Zdecydowałem, że mówienie o implementacji słabo spójnych iteratorów wykracza poza zakres tego pytania i odpowiedzi.
Stephen C

42

Są to typy raczej odporne na awarie i słabo spójne :

Iteratory z java.utilrzutu pakietu, ConcurrentModificationExceptionjeśli kolekcja została zmodyfikowana metodami kolekcji (dodaj / usuń) podczas iteracji

Iteratory z java.util.concurrentpakietu zwykle wykonują iterację po migawce i zezwalają na jednoczesne modyfikacje, ale mogą nie odzwierciedlać aktualizacji kolekcji po utworzeniu iteratora.


Iterator jest przykładem bezawaryjności, podczas gdy wyliczanie jest bezpieczne
Ajay Sharma

5
@AjaySharma - Niepoprawne z dwóch powodów. 1) Ani Iteratorlub Enumerationokreślić zachowanie jako nie-fast lub fail-safe. To konkretne implementacje (tj. Określone metody kolekcji iterator()/ elements()etc, które zwracają te obiekty) określają zachowanie. 2) Typowe implementacje wyliczania nieani odporne na awarie, ani bezpieczne .
Stephen C,

22

Jedyną różnicą jest to, że iterator odporny na awarie nie zgłasza żadnego wyjątku, w przeciwieństwie do iteratora odpornego na awarie.

Jeśli Collection jest modyfikowana strukturalnie, podczas gdy jeden wątek jest nad nią iterowany. Dzieje się tak, ponieważ pracują na klonie kolekcji zamiast oryginalnej kolekcji i dlatego są nazywane iteratorami odpornymi na awarie.

Iterator CopyOnWriteArrayList jest przykładem odpornego na awarie Iteratora, a także iteratora napisanego przez ConcurrentHashMap keySet jest również iteratorem bezpiecznym i nigdy nie rzuca ConcurrentModificationException w Javie.


Nie widzę, że iterator ConcurrentHashMap działa na clone () .. :( Czasami będzie odzwierciedlał niektóre aktualizacje podczas iteracji ..
Kanagavelu Sugumar

0

Ten scenariusz dotyczy „przetwarzania współbieżnego”, co oznacza, że ​​więcej niż jeden użytkownik uzyskuje dostęp do tego samego zasobu. W takiej sytuacji jeden z użytkowników próbuje zmodyfikować ten zasób, co powoduje „ConcurrentProcessingException”, ponieważ w takim przypadku inny użytkownik otrzymuje nieprawidłowe dane. Oba te typy odnoszą się do tego rodzaju sytuacji.

Krótko mówiąc,

Szybka awaria:

  • Iteratory natychmiast zgłaszają ConcurrentModificationException, jeśli nastąpi modyfikacja strukturalna (dodawanie, aktualizowanie, usuwanie).
  • Przykład: ArrayList, HashMap, TreeSet

Bezpieczny:

  • Tutaj Iteratory nie zgłaszają żadnego wyjątku, ponieważ działają na klonie kolekcji, a nie na oryginalnym. Tak więc, są to iteratory odporne na awarie.
  • Przykład: CopyOnWriteArrayList, ConcurrentHashMap
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.