Egyidejűség, BlockingQueues (Java 7) – 1

– Szia Amigo!

– Szia, Kim!

– Ma a párhuzamosságról fogok mesélni.

" A Concurrency egy Java osztálykönyvtár, amely speciális osztályokat tartalmaz, amelyeket több szálból történő munkára optimalizáltak. Ez egy nagyon érdekes és kiterjedt téma. De ma csak egy bevezetést fogunk kapni. A csomag neve java.util. párhuzamos csomag. Mesélek néhány érdekes óráról."

" Atomtípusok. "

"Már tudod, hogy még a count++ sem szálbiztos művelet. Ha egy változót 1-gyel növelünk, akkor valójában három művelet történik. Ennek eredményeként a változó megváltoztatásakor ütközés léphet fel."

– Igen, Ellie azt mondta nem régen:

1. szál 2. szál Eredmény
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Pontosan. Aztán a Java adattípusokat adott hozzá, hogy ezeket a műveleteket egyben, azaz atomosan (az atom oszthatatlan) hajtsa végre."

"Például a Java rendelkezik AtomicInteger, AtomicBoolean, AtomicDouble stb.

"Tegyük fel, hogy létre kell hoznunk egy "számláló" osztályt:

Példa
class Counter
{
 private int c = 0;

 public void increment()
 {
  c++;
 }

 public void decrement()
 {
  c--;
 }

 public int value()
 {
  return c;
 }
}

– Hogyan tenné szálbiztossá az ebbe az osztályba tartozó objektumokat?

"Nos, az összes metódust szinkronizálnám, és készen is vagyok vele:"

Példa
class synchronized Counter
{
 private int c = 0;

 public synchronized void increment()
 {
  c++;
 }

 public synchronized void decrement()
 {
  c--;
 }

 public synchronized int value()
 {
  return c;
 }
}

"Jó munka. De hogyan nézne ki, ha atomtípusokat használnánk:"

Példa
class AtomicCounter
{
 private AtomicInteger c = new AtomicInteger(0);

 public void increment()
 {
  c.incrementAndGet();
 }

 public void decrement()
 {
  c.decrementAndGet();
 }

 public int value()
 {
  return c.get();
 }
}

"A te osztályod és az én osztályom is ugyanúgy működik, de az AtomicIntegerrel rendelkező osztály gyorsabban működik."

– Nos, ez kicsi különbség?

"Igen. Tapasztalataim alapján mindig azt javaslom, hogy szinkronizálja a vezetést. Csak akkor kezdje el átírni a kódot, hogy az atomi típusokat használja tudni, hogy léteznek ilyen típusok. Még ha nem is használja őket aktívan, mindig fennáll az esélye, hogy kódba ütközik, ahol használják őket."

– Egyetértek. Ennek van értelme.

"Mellesleg, észrevette, hogy az atomtípusok nem változtathatók ? A standard Integer osztállyal ellentétben az AtomicInteger tartalmaz módszereket a belső állapot megváltoztatására."

"Értem. Csakúgy, mint a String és a StringBuffer ."

– Igen, valami ilyesmi.

" Szálbiztos gyűjtemények. "

"Egy ilyen gyűjtemény példájaként bemutathatom a ConcurrentHashMap-et. Hogyan tennéd a HashMapot szálbiztossá?"

"Minden metódusát szinkronizálja?"

"Persze, de most képzeld el, hogy van egy ilyen SynchronizedHashMap-ed, és több tucat szál éri el. És másodpercenként százszor új bejegyzés kerül a térképre, és közben az egész objektumot zárolják az olvasáshoz és az íráshoz."

"Nos, ez a szokásos megközelítés. Mit tehetsz?"

– A Java készítői kitaláltak néhány klassz dolgot.

"Először is egyetlen blokkban tárolják az adatokat egy ConcurrentHashMap-ben, de azokat "vödör"-nek nevezett részekre osztják fel. És ha valaki megváltoztatja az adatokat egy ConcurrentHashMap-ben, akkor csak az elért tárolót zároljuk, nem pedig a teljes objektumot. szó szerint sok szál képes egyszerre megváltoztatni az objektumot."

"Másodszor, emlékszel arra, hogy a lista/térkép elemei között nem lehet egyszerre átmásolni és a listát módosítani? Az ilyen kód kivételt dob:"

Ne ismételje meg a gyűjtemény elemeit egy ciklusban, és egyidejűleg módosítsa azt
HashMap<String, Integer> map = new HashMap<String, Integer>();

for (String key: map.keySet())
{
 if (map.get(key) == 0)
  map.remove(key);
}

"De a ConcurrentHashMapben a következőket teheti:"

Ne ismételje meg egy ciklusban a gyűjtemény elemeit, és egyidejűleg változtassa meg"
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();

for (String key: map.keySet())
{
 if (map.get(key) == 0)
  map.remove(key);
}

"A párhuzamos csomagnak számos előnye van. Csak nagyon jól meg kell értenünk ezeket az osztályokat, hogy használni tudjuk őket."

– Értem. Köszönöm, Kim. Ezek igazán érdekes órák. Remélem, egyszer majd virtuóz módjára elsajátítom őket.