Sobes.tech
Middle

Šta možete reći o višeslojnim kolekcijama u Javi?

sobes.tech АИ

Одговор од АИ

Колекције са више нитова у Јави пружају безбедне начине рада са подацима из више нитова истовремено, спречавајући услове трка и друге проблеме синхронизације.

Основни интерфејси и класе укључују:

  • ConcurrentMap: Проширење Map који обезбеђује атомске операције.
    • ConcurrentHashMap: Високо перформансна реализација која не блокира целу мапу током измена. Обезбеђује безбедност за више нитова без потпуног закључавања.
  • CopyOnWriteArrayList и CopyOnWriteArraySet: Колекције безбедне за више нитова, које при свакој измене праве копију основног низа. Погодне су за колекције које се често читају и ретко мењају. Читање се одвија без блокирања.
  • BlockingQueue: Интерфејс реда који подржава операције чекања, док ред не постане празан или пун. Користи се за организовање интеракције између нитова, нпр. у моделу произвођач-утрошилац.
    • ArrayBlockingQueue: Реализација BlockingQueue заснована на низу са фиксном капацитетом.
    • LinkedBlockingQueue: Реализација BlockingQueue заснована на повезаном списку са опционим капацитетом.
    • SynchronousQueue: Ред са нултом капацитетом. Сваке операције уметања чека на одговарајућу операцију уклањања и обрнуто.
  • ConcurrentLinkedQueue: Безбедна за више нитова реализација Queue заснована на повезаном списку. Не подржава блокирајуће операције.

Разлике у односу на синхронизоване колекције (Collections.synchronizedList, Collections.synchronizedMap и др.):

  • Синхронизоване колекције користе потпуно закључавање на нивоу објекта, што може смањити перформансе при високој конкуренцији.
  • Колекције са више нитова, као што је ConcurrentHashMap, користе финије закључавање или друге механизме за боље перформансе.
  • Итератори синхронизованих колекција могу бацити ConcurrentModificationException током измене колекције током итерације из друге нитове. Итератори колекција са више нитова су обично отпорнији на такве промене.

Избор конкретне колекције са више нитова зависи од сценарија употребе: учесталост читања/писања, потреба за блокирајућим операцијама, захтеви за перформансама итд.

Пример коришћења ConcurrentHashMap:

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); // Безбедна за више нитова операција
    }

    public Integer getValue(String key) {
        return map.get(key); // Безбедна за више нитова операција
    }

    public void incrementValue(String key) {
        // Атомска операција: ако кључ не постоји, постави 1, иначе увећа постојећу вредност
        map.compute(key, (k, v) -> (v == null) ? 1 : v + 1);
    }
}

Пример коришћења BlockingQueue:

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

public class ProducerConsumer {

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

    // Производни поток
    public void produce(Integer item) throws InterruptedException {
        queue.put(item); // Блокира ако је ред пун
        System.out.println("Produced: " + item);
    }

    // Потрошачки поток
    public Integer consume() throws InterruptedException {
        Integer item = queue.take(); // Блокира ако је ред празан
        System.out.println("Consumed: " + item);
        return item;
    }
}