Guide til CopyOnWriteArrayList

1. Oversikt

I denne raske artikkelen ser vi på CopyOnWriteArrayList fra java.util.concurrent pakke.

Dette er en veldig nyttig konstruksjon i flertrådede programmer - når vi vil gjenta over en liste på en trådsikker måte uten en eksplisitt synkronisering.

2. CopyOnWriteArrayList API

Utformingen av CopyOnWriteArrayList bruker en interessant teknikk for å gjøre den trådsikker uten behov for synkronisering. Når vi bruker noen av endringsmetodene - for eksempel legge til() eller fjerne() - hele innholdet i CopyOnWriteArrayList kopieres til den nye interne kopien.

På grunn av dette enkle faktum, vi kan gjentas over listen på en trygg måte, selv når samtidig endring skjer.

Når vi ringer til iterator () metoden på CopyOnWriteArrayList, vi får tilbake en Iterator støttet av det uforanderlige øyeblikksbildet av innholdet i CopyOnWriteArrayList.

Innholdet er en nøyaktig kopi av data som er inne i en ArrayList fra tiden da Iterator ble laget. Selv om en annen tråd i mellomtiden legger til eller fjerner et element fra listen, gjør denne modifikasjonen en fersk kopi av dataene som skal brukes i ytterligere dataoppslag fra listen.

Kjennetegnene til denne datastrukturen gjør den spesielt nyttig i tilfeller når vi gjentar det oftere enn vi endrer den. Hvis det er vanlig å legge til elementer i vårt scenario, da CopyOnWriteArrayList vil ikke være et godt valg - fordi de ekstra kopiene definitivt vil føre til sub-par ytelse.

3. Iterere over CopyOnWriteArrayList Mens du setter inn

La oss si at vi lager en forekomst av CopyOnWriteArrayList som lagrer heltall:

CopyOnWriteArrayList numbers = new CopyOnWriteArrayList (new Integer [] {1, 3, 5, 8});

Deretter vil vi iterere over den matrisen, så vi lager en Iterator forekomst:

Iterator iterator = numbers.iterator ();

Etter Iterator er opprettet, legger vi til et nytt element i tall liste:

numbers.add (10);

Husk at når vi oppretter en iterator for CopyOnWriteArrayList, vi får et uforanderlig øyeblikksbilde av dataene i listen på den tiden iterator () ble kalt.

På grunn av det, mens vi gjentar det, ser vi ikke tallet 10 i iterasjonen:

Listeresultat = ny LinkedList (); iterator.forEachRemaining (resultat :: legg til); assertThat (resultat) .containsOnly (1, 3, 5, 8);

Etterfølgende iterasjon med nyopprettet Iterator vil også returnere nummeret 10 som ble lagt til:

Iterator iterator2 = numbers.iterator (); Liste resultat2 = ny LinkedList (); iterator2.forEachRemaining (result2 :: add); assertThat (result2) .containsOnly (1, 3, 5, 8, 10);

4. Det er ikke tillatt å fjerne det mens jegtererer

De CopyOnWriteArrayList ble opprettet for å tillate muligheten for sikker iterering over elementer selv når den underliggende listen blir endret.

På grunn av kopimekanismen, er fjerne() operasjon på retur Iterator er ikke tillatt - resulterer med Ikke-støttetOperasjonseksept:

@Test (forventet = ikke støttetOperationException.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. Konklusjon

I denne raske opplæringen så vi på CopyOnWriteArrayList implementering fra java.util.concurrent pakke.

Vi så den interessante semantikken i denne listen og hvordan den kan gjentas på en trådsikker måte, mens andre tråder kan fortsette å sette inn eller fjerne elementer fra den.

Implementeringen av alle disse eksemplene og kodebitene finnes i GitHub-prosjektet - dette er et Maven-prosjekt, så det skal være enkelt å importere og kjøre som det er.


$config[zx-auto] not found$config[zx-overlay] not found