Bevezetés a szinkronizált Java-gyűjteményekbe

1. Áttekintés

A gyűjtemények keretrendszere a Java kulcseleme. Széleskörű interfészeket és megvalósításokat biztosít, amely lehetővé teszi számunkra a különböző típusú gyűjtemények egyszerű létrehozását és manipulálását.

Bár a sima, szinkronizálatlan gyűjtemények használata összességében egyszerű, ijesztő és hibára hajlamos folyamatsá válhat a többszálas környezetekben történő munkavégzés során (más néven egyidejű programozás).

Ezért a Java platform erőteljes támogatást nyújt ehhez a forgatókönyvhöz különböző szinkronizálások révén burkolók keretében végrehajtott Gyűjtemények osztály.

Ezek a csomagolók megkönnyítik a szállított gyűjtemények szinkronizált nézeteinek létrehozását több statikus gyári módszer segítségével.

Ebben az oktatóanyagban mélyen belemerülünk ezekbe statikus szinkronizáló burkolók. Emellett kiemeljük a szinkronizált és az egyidejű gyűjtemények közötti különbséget.

2. A synchronizedCollection () Módszer

Az első szinkronizáló burkoló, amelyet ebben a körben lefedünk, a synchronizedCollection () módszer. Ahogy a neve is sugallja, szálbiztos gyűjteményt ad vissza a megadottal alátámasztva Gyűjtemény.

Most, hogy jobban megértsük, hogyan kell használni ezt a módszert, hozzunk létre egy alapegység tesztet:

Gyűjtemény syncCollection = Collections.synchronizedCollection (új ArrayList ()); Futható listOperations = () -> {syncCollection.addAll (Arrays.asList (1, 2, 3, 4, 5, 6)); }; Menetszál1 = új Szál (listOperations); Menetszál2 = new Szál (listOperations); thread1.start (); thread2.start (); szál1.csatlakozzon (); szál2.csatlakozzon (); assertThat (syncCollection.size ()). isEqualTo (12); } 

Amint a fentiekből látható, a mellékelt gyűjtemény szinkronizált nézetének létrehozása ezzel a módszerrel nagyon egyszerű.

Annak bemutatására, hogy a módszer valóban szálbiztos gyűjteményt ad vissza, először létre kell hoznunk pár szálat.

Ezt követően beadunk egy a Futható például a konstruktőikbe, lambda kifejezés formájában. Ezt tartsuk szem előtt Futható egy funkcionális interfész, ezért egy lambda kifejezéssel helyettesíthetjük.

Végül csak azt ellenőrizzük, hogy minden szál hat elemet ad-e hozzá a szinkronizált gyűjteményhez, így a végleges mérete tizenkét.

3. Az synchronizedList () Módszer

Hasonlóképpen, hasonló a synchronizedCollection () módszerrel használhatjuk a synchronizedList () burkoló szinkronizált létrehozásához Lista.

Ahogy számíthatunk rá, a metódus visszaadja a megadott szálbiztonsági nézetét Lista:

List syncList = Collections.synchronizedList (új ArrayList ());

Nem meglepő, hogy a synchronizedList () a módszer majdnem azonos a magasabb szintű megfelelőjével, synchronizedCollection ().

Ezért, ahogy az előző egységtesztnél tettük, egyszer létrehoztunk egy szinkronizáltat Lista, több szálat is szaporíthatunk. Ezt követően felhasználjuk őket a cél eléréséhez / manipulálásához Lista szálbiztos módon.

Ezenkívül, ha egy szinkronizált gyűjteményt szeretnénk iterálni és megakadályozni a váratlan eredményeket, akkor kifejezetten meg kell adnunk a hurok saját szálbiztos megvalósítását. Ezért ezt elérhetnénk az a használatával szinkronizált Blokk:

List syncCollection = Collections.synchronizedList (Tömbök.asList ("a", "b", "c")); List uppercasedCollection = new ArrayList (); Futható listOperations = () -> {szinkronizált (syncCollection) {syncCollection.forEach ((e) -> {uppercasedCollection.add (e.toUpperCase ());}); }}; 

Minden olyan esetben, amikor egy szinkronizált gyűjteményen kell ismétlnünk, meg kell valósítanunk ezt az idiómát. Ennek oka, hogy a szinkronizált gyűjtemény iterációját többszörös hívás útján hajtják végre a gyűjteménybe. Ezért ezeket egyetlen atomi műveletként kell végrehajtani.

A szinkronizált blokk biztosítja a művelet atomosságát.

4. A synchronizedMap () Módszer

A Gyűjtemények osztály megvalósít egy másik ügyes szinkronizáló burkolót, az úgynevezett synchronizedMap (). Használhatnánk a szinkronizált adatok egyszerű létrehozására Térkép.

A módszer visszaadja a szállított szálbiztonsági nézetét Térkép végrehajtás:

Map syncMap = Collections.synchronizedMap (új HashMap ()); 

5. A synchronizedSortedMap () Módszer

Van egy megfelelő megvalósítása is a synchronizedMap () módszer. Ez az úgynevezett synchronizedSortedMap (), amelyet felhasználhatunk egy szinkronizált létrehozásához SortedMap példa:

Map syncSortedMap = Collections.synchronizedSortedMap (új TreeMap ()); 

6. A synchronizedSet () Módszer

Ezután, ebben a felülvizsgálatban továbblépve, megvan a synchronizedSet () módszer. Ahogy a neve is mutatja, lehetővé teszi számunkra a szinkronizált létrehozást Készletek minimális felhajtással.

A burkoló egy szálbiztos gyűjteményt ad vissza, amelyet a megadott támogat Készlet:

Set syncSet = Collections.synchronizedSet (új HashSet ()); 

7. Az synchronizedSortedSet () Módszer

Végül az utolsó szinkronizáló burkoló, amelyet itt bemutatunk synchronizedSortedSet ().

Hasonló az eddig áttekintett többi burkoló megvalósításhoz, a metódus az adott szálbiztos verzióját adja vissza SortedSet:

SortedSet syncSortedSet = Collections.synchronizedSortedSet (új TreeSet ()); 

8. Szinkronizált és egyidejű gyűjtemények

Eddig a pontig alaposabban megvizsgáltuk a gyűjtemény keretrendszer szinkronizálási csomagolóit.

Most összpontosítsunk a szinkronizált és az egyidejű gyűjtemények közötti különbségek, mint például ConcurrentHashMap és BlockingQueue megvalósítások.

8.1. Szinkronizált gyűjtemények

A szinkronizált gyűjtemények szálbiztonságot érnek el a belső zárolás révén, és a teljes gyűjtemények zárolva vannak. A belső zárolás szinkronizált blokkokon keresztül valósul meg a becsomagolt gyűjtemény módszerein belül.

Ahogy számíthatunk rá, a szinkronizált gyűjtemények biztosítják az adatok konzisztenciáját / integritását többszálas környezetekben. Előfordulhat azonban, hogy büntetéssel jár a teljesítmény, mivel egyszerre csak egyetlen szál férhet hozzá a gyűjteményhez (más néven szinkronizált hozzáférés).

Részletes útmutató a használathoz szinkronizált módszerek és blokkok, kérjük, olvassa el a témával foglalkozó cikkünket.

8.2. Egyidejű gyűjtemények

Egyidejű gyűjtemények (pl. ConcurrentHashMap), érje el a szálbiztonságot azáltal, hogy adatait szegmensekre osztja. A ConcurrentHashMappéldául különböző szálak zárolást szerezhetnek az egyes szegmensekben, így több szál is hozzáférhet a Térkép egyidejűleg (más néven egyidejű hozzáférés).

Egyidejű gyűjtemények sokkal teljesítőbb, mint a szinkronizált gyűjtemények, az egyidejű szálhozzáférés eredendő előnyei miatt.

Tehát a szálbiztos kollekció típusának megválasztása az egyes felhasználási esetek követelményeitől függ, és ennek megfelelően kell értékelni.

9. Következtetés

Ebben a cikkben alaposan megvizsgáltuk a szinkronizációs csomagolók készletét, amely a Gyűjtemények osztály.

Emellett rávilágítottunk a szinkronizált és az egyidejű gyűjtemények közötti különbségekre, és megvizsgáltuk az általuk alkalmazott megközelítéseket is a szálbiztonság eléréséhez.

Szokás szerint a cikkben bemutatott összes kódminta elérhető a GitHubon.