Колекція CopyOnWrite
Ми вже розглянули багато синхронізованих колекцій, і якщо ви опанували інші, ця буде ще простішою для розуміння.
Приклад із реального життя
Вебзастосунок, який використовує CopyOnWriteArrayList для зберігання підписників на події. Декілька потоків можуть одночасно отримувати список поточних підписників для сповіщення їх про зміни, у той час як інші потоки можуть додавати або видаляти підписників.
Відмінності від інших типів
Колекції CopyOnWrite створюють копію колекції щоразу при внесенні змін, що гарантує, що операції читання не блокуються змінами даних, забезпечуючи таким чином потокобезпечність для читання, хоча операції запису не є потокобезпечними, оскільки виконуються на окремій копії колекції.
CopyOnWrite-подання:
Як видно на зображенні, при додаванні нового елемента створюється копія цієї структури даних; усі потоки, які працювали з цією колекцією до її зміни, продовжать свою роботу без жодних проблем, оскільки ці зміни не вплинуть на копію CopyOnWrite, яку вони використовують!
CopyOnWriteArraySet
CopyOnWriteArraySet — це потокобезпечна реалізація множини на основі CopyOnWriteArrayList. Вона гарантує потокобезпечність шляхом створення нової копії базової множини щоразу, коли відбувається зміна, така як додавання або видалення елементів.
Такий підхід особливо корисний, коли множина часто читається і рідко змінюється, оскільки забезпечує послідовне відображення множини для всіх потоків без необхідності синхронізації.
CopyOnWriteArrayList
CopyOnWriteArrayList — це потокобезпечний варіант ArrayList, який забезпечує потокобезпечність шляхом створення нової копії базового масиву при кожній зміні.
Ця конструкція пропонує відмовостійкий ітератор, який не генерує ConcurrentModificationException, оскільки працює зі знімком масиву, зробленим у момент створення ітератора. Найкраще підходить для ситуацій, коли операції читання значно переважають над операціями запису, оскільки накладні витрати на копіювання всього масиву при кожному записі можуть бути значними.
Практичний приклад використання
Методи колекції CopyOnWrite
addIfAbsent(E e): Додає елемент до списку лише у випадку, якщо його ще немає у списку/множині.
Main.java
123456789101112131415161718192021package com.example; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); // Attempt to add a duplicate element list.addIfAbsent("apple"); // This will not add "apple" again // Adding a new element list.addIfAbsent("orange"); // This will add "orange" System.out.println(list); // Output: [apple, banana, orange] } }
У цьому прикладі "apple" не додається повторно, оскільки вже існує у списку. Метод addIfAbsent() запобігає дублюванню записів, підтримуючи унікальність елементів.
addAllAbsent(Collection<? extends E> c): Додає всі елементи із вказаної колекції до списку/множини, ігноруючи вже існуючі елементи.
Main.java
12345678910111213141516171819202122package com.example; import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); List<String> newFruits = Arrays.asList("banana", "cherry", "date"); // Adding elements from the collection, ignoring duplicates list.addAllAbsent(newFruits); System.out.println(list); // Output: [apple, banana, cherry, date] } }
У цьому прикладі "banana" вже присутній у list, тому addAllAbsent() не додасть його знову. Метод гарантує, що лише унікальні елементи з наданої колекції будуть додані до list.
Усі інші методи колекцій CopyOnWrite подібні до методів їхніх батьківських колекцій; вони просто копіюють стан колекції щоразу, коли відбуваються зміни.
Обмеження та переваги
😔Обмеження:
Колекції CopyOnWrite мають суттєві обмеження. Вони мають витрати пам'яті через створення нової копії колекції щоразу при зміні, що може бути значним. Такий дизайн робить їх менш придатними для сценаріїв, де потрібні часті зміни даних.
💪Переваги:
З іншого боку, колекції CopyOnWrite мають значні переваги. Вони надзвичайно ефективні для читання даних у багатопотоковому середовищі. Ці колекції працюють особливо добре у ситуаціях, коли операцій читання значно більше, ніж операцій запису, що робить їх чудовим вибором для таких випадків.
Однак через копіювання при кожній зміні колекції CopyOnWrite можуть споживати більше пам'яті та не підходять для сценаріїв із частими операціями запису. Вони є найбільш ефективними, коли операції читання переважають над операціями запису.
1. Що відбувається при виклику методу addIfAbsent(E e) у CopyOnWriteArrayList?
2. Чому колекції CopyOnWrite особливо підходять для сценаріїв із частим читанням і рідкісними змінами даних?
Дякуємо за ваш відгук!
Запитати АІ
Запитати АІ
Запитайте про що завгодно або спробуйте одне із запропонованих запитань, щоб почати наш чат
What are some common use cases for CopyOnWrite collections?
Can you explain the main differences between CopyOnWriteArrayList and CopyOnWriteArraySet?
When should I avoid using CopyOnWrite collections?
Awesome!
Completion rate improved to 3.33
Колекція CopyOnWrite
Свайпніть щоб показати меню
Ми вже розглянули багато синхронізованих колекцій, і якщо ви опанували інші, ця буде ще простішою для розуміння.
Приклад із реального життя
Вебзастосунок, який використовує CopyOnWriteArrayList для зберігання підписників на події. Декілька потоків можуть одночасно отримувати список поточних підписників для сповіщення їх про зміни, у той час як інші потоки можуть додавати або видаляти підписників.
Відмінності від інших типів
Колекції CopyOnWrite створюють копію колекції щоразу при внесенні змін, що гарантує, що операції читання не блокуються змінами даних, забезпечуючи таким чином потокобезпечність для читання, хоча операції запису не є потокобезпечними, оскільки виконуються на окремій копії колекції.
CopyOnWrite-подання:
Як видно на зображенні, при додаванні нового елемента створюється копія цієї структури даних; усі потоки, які працювали з цією колекцією до її зміни, продовжать свою роботу без жодних проблем, оскільки ці зміни не вплинуть на копію CopyOnWrite, яку вони використовують!
CopyOnWriteArraySet
CopyOnWriteArraySet — це потокобезпечна реалізація множини на основі CopyOnWriteArrayList. Вона гарантує потокобезпечність шляхом створення нової копії базової множини щоразу, коли відбувається зміна, така як додавання або видалення елементів.
Такий підхід особливо корисний, коли множина часто читається і рідко змінюється, оскільки забезпечує послідовне відображення множини для всіх потоків без необхідності синхронізації.
CopyOnWriteArrayList
CopyOnWriteArrayList — це потокобезпечний варіант ArrayList, який забезпечує потокобезпечність шляхом створення нової копії базового масиву при кожній зміні.
Ця конструкція пропонує відмовостійкий ітератор, який не генерує ConcurrentModificationException, оскільки працює зі знімком масиву, зробленим у момент створення ітератора. Найкраще підходить для ситуацій, коли операції читання значно переважають над операціями запису, оскільки накладні витрати на копіювання всього масиву при кожному записі можуть бути значними.
Практичний приклад використання
Методи колекції CopyOnWrite
addIfAbsent(E e): Додає елемент до списку лише у випадку, якщо його ще немає у списку/множині.
Main.java
123456789101112131415161718192021package com.example; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); // Attempt to add a duplicate element list.addIfAbsent("apple"); // This will not add "apple" again // Adding a new element list.addIfAbsent("orange"); // This will add "orange" System.out.println(list); // Output: [apple, banana, orange] } }
У цьому прикладі "apple" не додається повторно, оскільки вже існує у списку. Метод addIfAbsent() запобігає дублюванню записів, підтримуючи унікальність елементів.
addAllAbsent(Collection<? extends E> c): Додає всі елементи із вказаної колекції до списку/множини, ігноруючи вже існуючі елементи.
Main.java
12345678910111213141516171819202122package com.example; import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); List<String> newFruits = Arrays.asList("banana", "cherry", "date"); // Adding elements from the collection, ignoring duplicates list.addAllAbsent(newFruits); System.out.println(list); // Output: [apple, banana, cherry, date] } }
У цьому прикладі "banana" вже присутній у list, тому addAllAbsent() не додасть його знову. Метод гарантує, що лише унікальні елементи з наданої колекції будуть додані до list.
Усі інші методи колекцій CopyOnWrite подібні до методів їхніх батьківських колекцій; вони просто копіюють стан колекції щоразу, коли відбуваються зміни.
Обмеження та переваги
😔Обмеження:
Колекції CopyOnWrite мають суттєві обмеження. Вони мають витрати пам'яті через створення нової копії колекції щоразу при зміні, що може бути значним. Такий дизайн робить їх менш придатними для сценаріїв, де потрібні часті зміни даних.
💪Переваги:
З іншого боку, колекції CopyOnWrite мають значні переваги. Вони надзвичайно ефективні для читання даних у багатопотоковому середовищі. Ці колекції працюють особливо добре у ситуаціях, коли операцій читання значно більше, ніж операцій запису, що робить їх чудовим вибором для таких випадків.
Однак через копіювання при кожній зміні колекції CopyOnWrite можуть споживати більше пам'яті та не підходять для сценаріїв із частими операціями запису. Вони є найбільш ефективними, коли операції читання переважають над операціями запису.
1. Що відбувається при виклику методу addIfAbsent(E e) у CopyOnWriteArrayList?
2. Чому колекції CopyOnWrite особливо підходять для сценаріїв із частим читанням і рідкісними змінами даних?
Дякуємо за ваш відгук!