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.