Vejledning til CopyOnWriteArrayList

1. Oversigt

I denne hurtige artikel ser vi på CopyOnWriteArrayList fra java.util.concurrent pakke.

Dette er en meget nyttig konstruktion i multitrådede programmer - når vi vil gentage en liste på en trådsikker måde uden en eksplicit synkronisering.

2. CopyOnWriteArrayList API

Designet af CopyOnWriteArrayList bruger en interessant teknik til at gøre den trådsikker uden behov for synkronisering. Når vi bruger en af ​​ændringsmetoderne - som f.eks tilføje() eller fjern () - hele indholdet af CopyOnWriteArrayList kopieres til den nye interne kopi.

På grund af denne enkle kendsgerning vi kan gentage listen over på en sikker måde, selv når der sker samtidig ændringer.

Når vi ringer til iterator () metode til CopyOnWriteArrayList, vi får tilbage en Iterator bakket op af det uforanderlige øjebliksbillede af indholdet af CopyOnWriteArrayList.

Dens indhold er en nøjagtig kopi af data, der er inde i en ArrayList fra det tidspunkt, hvor Iterator var lavet. Selvom der i mellemtiden tilføjes eller fjernes en anden tråd fra et element fra listen, foretager denne ændring en ny kopi af de data, der vil blive brugt i enhver yderligere dataopslag fra listen.

Kendetegnene ved denne datastruktur gør det særligt nyttigt i tilfælde, hvor vi gentager det ofte, end vi ændrer det. Hvis tilføjelse af elementer er en almindelig handling i vores scenario, så CopyOnWriteArrayList vil ikke være et godt valg - fordi de ekstra kopier helt sikkert vil føre til sub-par performance.

3. Iterering over CopyOnWriteArrayList Mens du indsætter

Lad os sige, at vi opretter en forekomst af CopyOnWriteArrayList der gemmer heltal:

CopyOnWriteArrayList numre = ny CopyOnWriteArrayList (nyt heltal [] {1, 3, 5, 8});

Dernæst vil vi gentage dette array, så vi opretter en Iterator eksempel:

Iterator iterator = numbers.iterator ();

Efter Iterator er oprettet, tilføjer vi et nyt element til numre liste:

numbers.add (10);

Husk, at når vi opretter en iterator til CopyOnWriteArrayList, vi får et uforanderligt øjebliksbillede af dataene på listen på det tidspunkt iterator () blev kaldt.

På grund af det, mens vi gentager det, ser vi ikke antallet 10 i iteration:

Listeresultat = ny LinkedList (); iterator.forEachRemaining (resultat :: tilføj); hævder, at (resultat). indeholder kun (1, 3, 5, 8);

Efterfølgende iteration ved hjælp af nyoprettet Iterator vil også returnere nummeret 10, der blev tilføjet:

Iterator iterator2 = numbers.iterator (); Listeresultat2 = ny LinkedList (); iterator2.forEachRemaining (result2 :: add); hævder, at (resultat2). indeholder kun (1, 3, 5, 8, 10);

4. Det er ikke tilladt at fjerne det, mens det gentages

Det CopyOnWriteArrayList blev oprettet for at give mulighed for sikker iterering over elementer, selv når den underliggende liste bliver ændret.

På grund af kopimekanismen, er fjerne() operation på den returnerede Iterator er ikke tilladt - resulterende med Ikke-understøttetOperationException:

@Test (forventet = UnsupportedOperationException.class) offentlig ugyldig nårIterateOverItAndTryToRemoveElement_thenShouldThrowException () {CopyOnWriteArrayList numbers = new CopyOnWriteArrayList (new Integer [] {1, 3, 5, 8} Iterator iterator = numbers.iterator (); mens (iterator.hasNext ()) {iterator.remove (); }}

5. Konklusion

I denne hurtige vejledning kiggede vi på CopyOnWriteArrayList implementering fra java.util.concurrent pakke.

Vi så den interessante semantik på denne liste, og hvordan den kan gentages på en trådsikker måde, mens andre tråde kan fortsætte med at indsætte eller fjerne elementer fra den.

Implementeringen af ​​alle disse eksempler og kodestykker findes i GitHub-projektet - dette er et Maven-projekt, så det skal være let at importere og køre, som det er.