Vodič za CopyOnWriteArrayList
1. Pregled
U ovom ćemo kratkom članku pogledati CopyOnWriteArrayList od java.util.concurrent paket.
Ovo je vrlo korisna konstrukcija u programima s više niti - kada želimo itirirati popis na nit-siguran način bez izričite sinkronizacije.
2. CopyOnWriteArrayList API
Dizajn CopyOnWriteArrayList koristi zanimljivu tehniku kako bi ga učinili sigurnim za konac bez potrebe za sinkronizacijom. Kada koristimo bilo koju od metoda modificiranja - kao što je dodati() ili ukloniti () - cjelokupni sadržaj CopyOnWriteArrayList se kopira u novu internu kopiju.
Zbog ove jednostavne činjenice, možemo prelistavati popis na siguran način, čak i kad se događa istodobna modifikacija.
Kad zovemo iterator () metoda na CopyOnWriteArrayList, vraćamo an Iterator potkrijepljen nepromjenjivom snimkom sadržaja CopyOnWriteArrayList.
Sadržaj je točna kopija podataka koji se nalaze u ArrayList iz vremena kada je Iterator kreiran je. Čak i ako u međuvremenu neka druga nit doda ili ukloni element sa popisa, ta izmjena čini novu kopiju podataka koji će se koristiti u bilo kojem daljnjem pretraživanju podataka s tog popisa.
Karakteristike ove strukture podataka čine je posebno korisnom u slučajevima kada je ponavljamo češće nego što je mijenjamo. Ako je dodavanje elemenata uobičajena operacija u našem scenariju, tada CopyOnWriteArrayList neće biti dobar izbor - jer će dodatne kopije definitivno dovesti do slabije izvedbe.
3. Iteriranje preko CopyOnWriteArrayList Tijekom umetanja
Recimo da stvaramo instancu CopyOnWriteArrayList koji pohranjuje cijele brojeve:
CopyOnWriteArrayList numbers = novi CopyOnWriteArrayList (novi cijeli broj [] {1, 3, 5, 8});
Dalje, želimo se iterirati preko tog niza, pa stvaramo Iterator primjer:
Iterator iterator = numbers.iterator ();
Nakon što Iterator je stvoren, dodajemo novi element u brojevi popis:
brojevi.add (10);
Imajte na umu da, kada kreiramo iterator za CopyOnWriteArrayList, dobivamo nepromjenjivu snimku podataka na popisu u to vrijeme iterator () bio pozvan.
Zbog toga, dok se ponavljamo, nećemo vidjeti broj 10 u iteraciji:
Rezultat popisa = novi LinkedList (); iterator.forEachRemaining (rezultat :: dodaj); assertThat (result) .containsOnly (1, 3, 5, 8);
Naknadna iteracija pomoću novostvorenog Iterator također će vratiti broj 10 koji je dodan:
Iterator iterator2 = numbers.iterator (); Popis rezultata2 = novi LinkedList (); iterator2.forEachRemaining (result2 :: add); assertThat (result2) .contentOnly (1, 3, 5, 8, 10);
4. Uklanjanje tijekom ponavljanja nije dopušteno
The CopyOnWriteArrayList stvoren je kako bi se omogućila mogućnost sigurnog ponavljanja elemenata čak i kada se temeljni popis promijeni.
Zbog mehanizma kopiranja, ukloniti() operacija na vraćenom Iterator nije dopušteno - rezultira s UnsupportedOperationException:
@Test (očekuje se = UnsupportedOperationException.class) javna praznina whenIterateOverItAndTryToRemoveElement_thenShouldThrowException () {CopyOnWriteArrayList numbers = new CopyOnWriteArrayList (new Integer [] {1, 3, 5, 8, 8, 1, 3, 5, 8, 8; Iterator iterator = numbers.iterator (); while (iterator.hasNext ()) {iterator.remove (); }}
5. Zaključak
U ovom smo brzom vodiču pogledali CopyOnWriteArrayList provedba iz java.util.concurrent paket.
Vidjeli smo zanimljivu semantiku ovog popisa i kako se može ponoviti na siguran način, dok ostale niti mogu nastaviti s umetanjem ili uklanjanjem elemenata s njega.
Provedbu svih ovih primjera i isječaka koda možete pronaći u projektu GitHub - ovo je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.