Sobes.tech
Middle

Mit tudsz mondani a Java több szálas gyűjteményeiről?

sobes.tech MI

Válasz az MI-től

A Java több szálú kollekciói biztonságos módokat kínálnak az adatok kezelésére több szálból egyszerre, megakadályozva a versenyhelyzeteket és más szinkronizációs problémákat.

A fő interfészek és osztályok a következők:

  • ConcurrentMap: Kibővíti a Map-et, atomikus műveleteket biztosítva.
    • ConcurrentHashMap: Magas teljesítményű megvalósítás, amely nem blokkolja az egész térképet módosításkor. Szálbiztos, anélkül hogy teljes zárolást alkalmazna.
  • CopyOnWriteArrayList és CopyOnWriteArraySet: Szálbiztos kollekciók, amelyek minden módosításkor másolatot készítenek az alap tömbről. Jó választás gyakran olvasott és ritkán módosított kollekciókhoz. Az olvasás zárolás nélkül történik.
  • BlockingQueue: Várakozó műveleteket támogató sor interfész, amely vár, amíg a sor nem lesz üres vagy tele. Szálak közötti interakció szervezésére használják, például producer-consumer mintában.
    • ArrayBlockingQueue: Fix kapacitású tömb alapú BlockingQueue megvalósítás.
    • LinkedBlockingQueue: Hozott lista alapú BlockingQueue megvalósítás, opcionális kapacitással.
    • SynchronousQueue: Null kapacitású sor. Minden beszúrási művelet várja a megfelelő kivételi műveletet és fordítva.
  • ConcurrentLinkedQueue: Szálbiztos, láncolt lista alapú Queue megvalósítás. Nem támogat blokkoló műveleteket.

A különbségek a szinkronizált kollekciókhoz (Collections.synchronizedList, Collections.synchronizedMap stb.) képest:

  • A szinkronizált kollekciók teljes zárolást alkalmaznak az objektum szintjén, ami magas verseny esetén csökkentheti a teljesítményt.
  • A több szálú kollekciók, mint például a ConcurrentHashMap, finomabb zárolási mechanizmusokat vagy más technikákat használnak a jobb teljesítmény érdekében.
  • A szinkronizált kollekciók iterátorai ConcurrentModificationException-t dobhatnak, ha a kollekciót módosítják egy másik szálból az iterálás közben. A több szálú kollekciók iterátorai általában ellenállóbbak az ilyen változásokkal szemben.

A konkrét több szálú kollekció kiválasztása a felhasználási szcenáriótól függ: olvasási/írási gyakoriság, zárolási műveletek szükségessége, teljesítménykövetelmények stb.

A ConcurrentHashMap használatának példája:

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentExample {

    private final ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    public void updateValue(String key, Integer value) {
        map.put(key, value); // Szálbiztos művelet
    }

    public Integer getValue(String key) {
        return map.get(key); // Szálbiztos művelet
    }

    public void incrementValue(String key) {
        // Atomikus művelet: ha a kulcs nem létezik, 1-et helyez el, különben növeli a meglévő értéket
        map.compute(key, (k, v) -> (v == null) ? 1 : v + 1);
    }
}

A BlockingQueue használatának példája:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;

public class ProducerConsumer {

    private final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);

    // Termelő szál
    public void produce(Integer item) throws InterruptedException {
        queue.put(item); // Blokkol, ha a sor tele van
        System.out.println("Produced: " + item);
    }

    // Fogyasztó szál
    public Integer consume() throws InterruptedException {
        Integer item = queue.take(); // Blokkol, ha a sor üres
        System.out.println("Consumed: " + item);
        return item;
    }
}