Sobes.tech
Middle

რა შეგიძლიათ თქვათ Java-ს მრავალთრაკული კოლექციების შესახებ?

sobes.tech AI

პასუხი AI-სგან

Java-да көп ағынды жинақтар бірнеше ағынмен жұмыс істеу үшін қауіпсіз тәсілдерді ұсынады, бұл жарыс жағдайларын және басқа синхрондау мәселелерін болдырмайды.

Негізгі интерфейстер мен кластар мыналарды қамтиды:

  • ConcurrentMap: Map-ты кеңейтеді, атомарлы операцияларды қамтамасыз етеді.
    • ConcurrentHashMap: Жоғары өнімділікке ие жүзеге асыру, өзгерту кезінде картаға толық блок салмайды. Ағын қауіпсіздігін толық блоктаусыз қамтамасыз етеді.
  • CopyOnWriteArrayList және CopyOnWriteArraySet: Ағындар қауіпсіз жинақтар, олар негізгі массивті кез келген өзгерту кезінде көшірмесін жасайды. Жиі оқылатын және сирек өзгертілетін жинақтарға жақсы сәйкес келеді. Оқу блокталмайды.
  • BlockingQueue: Күту операцияларын қолдайтын кезек интерфейсі, кезек бос немесе толық болғанша күтеді. Ағындар арасындағы өзара әрекетті ұйымдастыру үшін пайдаланылады, мысалы, producer-consumer үлгісінде.
    • 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;
    }
}