W Javie istnieją dwa typy iteratorów: odporne na awarie i szybkie.
Co to oznacza i czy jest między nimi różnica?
W Javie istnieją dwa typy iteratorów: odporne na awarie i szybkie.
Co to oznacza i czy jest między nimi różnica?
Odpowiedzi:
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 Enumeration
interfejsu 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 volatile
licznika w obiekcie kolekcji.
Iterator
utworzeniu aktualna wartość licznika jest osadzana w Iterator
obiekcie.Iterator
operacji 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ę ArrayList
bez 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ć
ConcurrentModificationException
na 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. "
setArray
każdą modyfikację.
Są to typy raczej odporne na awarie i słabo spójne :
Iteratory z java.util
rzutu pakietu, ConcurrentModificationException
jeśli kolekcja została zmodyfikowana metodami kolekcji (dodaj / usuń) podczas iteracji
Iteratory z java.util.concurrent
pakietu zwykle wykonują iterację po migawce i zezwalają na jednoczesne modyfikacje, ale mogą nie odzwierciedlać aktualizacji kolekcji po utworzeniu iteratora.
Iterator
lub Enumeration
okreś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 nie są ani odporne na awarie, ani bezpieczne .
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.
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:
Bezpieczny: