Sobes.tech
Middle

Ką galite pasakyti apie daugiagijines kolekcijas Java?

sobes.tech AI

Atsakymas iš AI

Java kalbos daugiabriaunės kolekcijos siūlo saugius būdus dirbti su duomenimis keliuose srautuose vienu metu, užkertant kelią lenktynių sąlygoms ir kitiems sinchronizacijos problemoms.

Pagrindiniai sąsajos ir klasės apima:

  • ConcurrentMap: Plečia Map, užtikrindama atomines operacijas.
    • ConcurrentHashMap: Aukšto našumo įgyvendinimas, kuris neblokuoja visos žemėlapio keičiant. Užtikrina srauto saugumą be visiško blokavimo.
  • CopyOnWriteArrayList ir CopyOnWriteArraySet: Srauto saugios kolekcijos, kurios sukuria kopiją pagrindinio masyvo bet kokio pakeitimo metu. Gerai tinka kolekcijoms, kurios dažnai skaitomos ir retai keičiamos. Skaitymas vyksta be blokavimo.
  • BlockingQueue: eilės sąsaja, palaikanti laukimo operacijas, kol eilė taps tuščia arba pilna. Naudojama tarpusavio sąveikai tarp srautų organizuoti, pvz., producer-consumer modelyje.
    • ArrayBlockingQueue: Fiksuotos talpos masyvo pagrindu įgyvendinta BlockingQueue.
    • LinkedBlockingQueue: Susietojo sąrašo pagrindu įgyvendinta BlockingQueue, su pasirenkama talpa.
    • SynchronousQueue: Nulinės talpos eilė. Kiekviena įterpimo operacija laukia atitinkamos ištraukimo operacijos ir atvirkščiai.
  • ConcurrentLinkedQueue: Srauto saugi susietojo sąrašo pagrindu įgyvendinta Queue. Nepalaiko blokuojančių operacijų.

Skirtumai nuo sinchronizuotų kolekcijų (Collections.synchronizedList, Collections.synchronizedMap ir kt.):

  • Sinchronizuotos kolekcijos naudoja viso objekto lygio blokavimą, kuris gali sumažinti našumą didelės konkurencijos atveju.
  • Daugiabriaunės kolekcijos, tokios kaip ConcurrentHashMap, naudoja smulkesnį blokavimą arba kitus mechanizmus geresniam našumui pasiekti.
  • Sinchronizuotų kolekcijų iteratorių gali mesti ConcurrentModificationException keičiant kolekciją kitame sraute. Daugiabriaunės kolekcijos dažniausiai yra atsparios tokiems pakeitimams.

Konkretaus daugiabriaunio kolekcijos pasirinkimas priklauso nuo naudojimo scenarijaus: skaitymo/rašymo dažnumo, blokuojančių operacijų poreikio, našumo reikalavimų ir kt.

ConcurrentHashMap naudojimo pavyzdys:

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); // Srauto saugi operacija
    }

    public Integer getValue(String key) {
        return map.get(key); // Srauto saugi operacija
    }

    public void incrementValue(String key) {
        // Atominių operacija: jei raktas neegzistuoja, įdės 1, kitaip padidins esamą reikšmę
        map.compute(key, (k, v) -> (v == null) ? 1 : v + 1);
    }
}

BlockingQueue naudojimo pavyzdys:

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

public class ProducerConsumer {

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

    // Gamintojas srautas
    public void produce(Integer item) throws InterruptedException {
        queue.put(item); // Blokuojasi, jei eilė pilna
        System.out.println("Produced: " + item);
    }

    // Vartotojo srautas
    public Integer consume() throws InterruptedException {
        Integer item = queue.take(); // Blokuojasi, jei eilė tuščia
        System.out.println("Consumed: " + item);
        return item;
    }
}