En introduksjon til synkroniserte Java-samlinger

1. Oversikt

Samlingsrammeverket er en nøkkelkomponent i Java. Det gir et omfattende antall grensesnitt og implementeringer, som lar oss lage og manipulere forskjellige typer samlinger på en enkel måte.

Selv om bruk av vanlige usynkroniserte samlinger generelt er enkelt, kan det også bli en skremmende og feilutsatt prosess når du arbeider i flertrådede miljøer (aka samtidig programmering).

Derfor gir Java-plattformen sterk støtte for dette scenariet gjennom annen synkronisering innpakninger implementert i Samlinger klasse.

Disse innpakningene gjør det enkelt å lage synkroniserte visninger av de medfølgende samlingene ved hjelp av flere statiske fabrikkmetoder.

I denne veiledningen, Vi tar et dypdykk i disse statisk synkroniseringspakker. Vi vil også markere forskjellen mellom synkroniserte samlinger og samtidige samlinger.

2. Den synchronizedCollection () Metode

Den første synkroniseringsomslaget som vi vil dekke i denne runden, er synchronizedCollection () metode. Som navnet antyder, den returnerer en trådsikker samling støttet av det angitte Samling.

For å forstå mer klart hvordan du bruker denne metoden, la oss lage en grunnleggende enhetstest:

Collection syncCollection = Collections.synchronizedCollection (ny ArrayList ()); Runnable listOperations = () -> {syncCollection.addAll (Arrays.asList (1, 2, 3, 4, 5, 6)); }; Trådtråd1 = ny tråd (listOperations); Trådtråd2 = ny tråd (listOperations); thread1.start (); thread2.start (); thread1.join (); thread2.join (); assertThat (syncCollection.size ()). er EqualTo (12); } 

Som vist ovenfor er det veldig enkelt å lage en synkronisert visning av den medfølgende samlingen med denne metoden.

For å demonstrere at metoden faktisk returnerer en trådsikker samling, oppretter vi først et par tråder.

Etter det injiserer vi deretter en Kjørbar eksempel inn i deres konstruktører, i form av et lambdauttrykk. La oss huske på det Kjørbar er et funksjonelt grensesnitt, så vi kan erstatte det med et lambdauttrykk.

Til slutt sjekker vi bare at hver tråd effektivt legger til seks elementer i den synkroniserte samlingen, så den endelige størrelsen er tolv.

3. Den synkronisert liste () Metode

Likeledes, lik den synchronizedCollection () metoden, kan vi bruke synkronisert liste () innpakning for å lage en synkronisert Liste.

Som vi kunne forvente, metoden returnerer en trådsikker visning av det angitte Liste:

Liste syncList = Collections.synchronizedList (ny ArrayList ());

Ikke overraskende er bruken av synkronisert liste () metoden ser nesten ut som sin motstykke på høyere nivå, synchronizedCollection ().

Derfor, som vi nettopp gjorde i forrige enhetstest, når vi har opprettet en synkronisert Liste, vi kan gyte flere tråder. Etter å ha gjort det, bruker vi dem til å få tilgang til / manipulere målet Liste på en trådsikker måte.

I tillegg, hvis vi ønsker å iterere over en synkronisert samling og forhindre uventede resultater, bør vi eksplisitt gi vår egen trådsikre implementering av loop. Derfor kunne vi oppnå det ved å bruke en synkronisert blokkere:

Liste syncCollection = Collections.synchronizedList (Arrays.asList ("a", "b", "c")); Liste oppercasedCollection = ny ArrayList (); Kjørbar listeOperasjoner = () -> {synkronisert (syncCollection) {syncCollection.forEach ((e) -> {uppercasedCollection.add (e.toUpperCase ());}); }}; 

I alle tilfeller der vi trenger å iterere over en synkronisert samling, bør vi implementere dette uttrykket. Dette skyldes at iterasjonen på en synkronisert samling utføres gjennom flere anrop til samlingen. Derfor må de utføres som en enkelt atomoperasjon.

Bruken av synkronisert blokk sørger for atomisiteten i operasjonen.

4. Den synchronizedMap () Metode

De Samlinger klasse implementerer et annet pent synkroniseringsomslag, kalt synchronizedMap (). Vi kan bruke den til å enkelt lage en synkronisert Kart.

Metoden returnerer en trådsikker visning av den medfølgende Kart gjennomføring:

Kart syncMap = Collections.synchronizedMap (nytt HashMap ()); 

5. Den synchronizedSortedMap () Metode

Det er også en motstykke implementering av synchronizedMap () metode. Det kalles synchronizedSortedMap (), som vi kan bruke til å lage en synkronisert SortedMap forekomst:

Kart syncSortedMap = Collections.synchronizedSortedMap (nytt TreeMap ()); 

6. Den synchronizedSet () Metode

Deretter fortsetter vi i denne anmeldelsen synchronizedSet () metode. Som navnet antyder, tillater det oss å lage synkronisert Settene med minimalt oppstyr.

Innpakningen returnerer en trådsikker samling støttet av det angitte Sett:

Sett syncSet = Collections.synchronizedSet (nytt HashSet ()); 

7. Den synchronizedSortedSet () Metode

Endelig er den siste synkroniseringsomslaget som vi viser her synchronizedSortedSet ().

I likhet med andre wrapper-implementeringer som vi har vurdert hittil, metoden returnerer en trådsikker versjon av gaven SortedSet:

SortedSet syncSortedSet = Collections.synchronizedSortedSet (new TreeSet ()); 

8. Synkronisert mot samtidige samlinger

Fram til dette punktet så vi nærmere på samlingenes rammeverk for synkronisering.

La oss nå fokusere på forskjellene mellom synkroniserte samlinger og samtidige samlinger, som for eksempel ConcurrentHashMap og BlockingQueue implementeringer.

8.1. Synkroniserte samlinger

Synkroniserte samlinger oppnår trådsikkerhet gjennom egenlåsing, og hele samlingene er låst. Egenlåsing implementeres via synkroniserte blokker innenfor den pakket inn samlingens metoder.

Som vi kanskje forventer, sikrer synkroniserte samlinger datakonsistens / integritet i miljøer med flere tråder. Imidlertid kan de komme med en straff i ytelse, da bare en enkelt tråd kan få tilgang til samlingen om gangen (aka synkronisert tilgang).

For en detaljert veiledning om hvordan du bruker synkronisert metoder og blokker, kan du sjekke artikkelen vår om emnet.

8.2. Samtidige samlinger

Samtidige samlinger (f.eks. ConcurrentHashMap), oppnå trådsikkerhet ved å dele dataene i segmenter. I en ConcurrentHashMapFor eksempel kan forskjellige tråder skaffe seg låser på hvert segment, slik at flere tråder kan få tilgang til Kart samtidig (aka samtidig tilgang).

Samtidige samlinger er mye mer performant enn synkroniserte samlinger, på grunn av de iboende fordelene med samtidig trådtilgang.

Så, valg av hvilken type trådsikker samling som skal brukes, avhenger av kravene i hvert brukssak, og det bør vurderes i samsvar med dette.

9. Konklusjon

I denne artikkelen tok vi en grundig titt på settet med synkroniseringspakker implementert i Samlinger klasse.

I tillegg markerte vi forskjellene mellom synkroniserte og samtidige samlinger, og så også på tilnærmingene de implementerer for å oppnå trådsikkerhet.

Som vanlig er alle kodeeksemplene vist i denne artikkelen tilgjengelig på GitHub.


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