Углубленное понимание потокобезопасного списка в Java: принцип и применение CopyOnWriteArrayList.
Углубленное понимание потокобезопасного списка в Java: принцип и применение CopyOnWriteArrayList.

1️⃣ Что такое CopyOnWrite (копирование при записи)

CopyOnWrite, также известный как копирование при записи (COW), — это стратегия оптимизации в области программирования. Основная идея этой стратегии заключается в том, что когда несколько вызывающих объектов (или потоков) одновременно обращаются к одному и тому же ресурсу, они совместно получают указатель на ресурс. Пока ни один вызывающий объект не пытается изменить ресурс, все вызывающие могут продолжать получать доступ к одному и тому же ресурсу. Однако как только вызывающая сторона попытается изменить ресурс, система скопирует копию ресурса вызывающей стороне, а другие вызывающие стороны по-прежнему будут видеть исходный ресурс. Этот процесс прозрачен для других вызывающих сторон, которые не знают, что ресурс был скопирован.

В Java CopyOnWriteArrayList и CopyOnWriteArraySet — это два класса, использующие эту стратегию. Оба класса расположены в пакете java.util.concurrent и являются потокобезопасными классами коллекций. Когда элементы коллекции необходимо изменить, они не будут изменяться непосредственно в исходной коллекции, а будут копировать новую коллекцию, а затем изменять ее в новой коллекции. После завершения изменения укажите ссылку на исходную коллекцию на новую коллекцию. Такая конструкция позволяет выполнять операции чтения без блокировки, тем самым улучшая производительность параллелизма.

В общем, CopyOnWrite — это стратегия оптимизации, подходящая для сценариев, в которых требуется больше чтения и меньше записи. Она обеспечивает разделение чтения и записи за счет копирования данных, повышая производительность параллелизма. Однако у него также есть некоторые потенциальные проблемы с производительностью, такие как повышенное использование памяти, снижение производительности записи и частая сборка мусора. Поэтому при их использовании вам необходимо идти на компромиссы и делать выбор на основе конкретных сценариев.

2️⃣Что такое CopyOnWriteArrayList

CopyOnWriteArrayListдаJavaпараллельный пакетjava.util.concurrentкласс в,он достигListинтерфейс。как следует из названия,

CopyOnWriteArrayList — это класс Java, расположенный в пакете java.util.concurrent. Это поточно-ориентированный вариант ArrayList, в котором все изменяемые операции (такие как добавление, установка и т. д.) реализуются путем создания новой копии базового массива, отсюда и название списка «копирование при записи».

Поскольку CopyOnWriteArrayList не вносит никаких изменений в список при обходе,Поэтому он никогда не выкинетConcurrentModificationExceptionаномалия。это изменение операции(нравитьсяaddsetждать)час,Будет копировать копию базового массива,Затем измените его в новом массиве,После завершения модификации переключите ссылку на базовый массив на новый массив. Такая конструкция позволяет выполнять операции чтения без блокировки.,тем самым улучшая производительность одновременного выполнения,Эта функция делает более безопасным выполнение операций обхода в многопоточной среде.

Однако в CopyOnWriteArrayList нет понятия «расширение». Каждая операция записи (например, добавление или удаление) требует копирования совершенно нового массива, что может вызвать проблемы с производительностью при частом выполнении операций записи, поскольку копирование всего массива занимает довольно много времени. Поэтому при использовании CopyOnWriteArrayList необходимо уделять особое внимание применимым сценариям. Вообще говоря, он больше подходит для сценариев, в которых требуется больше чтения и меньше записи.

3️⃣Как работает CopyOnWriteArrayList

CopyOnWriteArrayList — это потокобезопасный вариант ArrayList. Операции чтения могут выполняться без блокировки, что повышает производительность параллелизма.

В частности, CopyOnWriteArrayList имеет внутреннюю блокировку повторного входа (ReentrantLock) для обеспечения безопасности потоков, но эта блокировка используется только во время операций записи. При выполнении операции модификации поток сначала получает блокировку, затем копирует базовый массив и выполняет изменения в новом массиве. После завершения модификации убедитесь, что новый массив виден всем потокам через ссылку, измененную с помощью ключевого слова Летучий. Поскольку операции чтения не требуют получения блокировки, несколько потоков могут выполнять операции чтения одновременно, не мешая друг другу.

3.1 Несколько преимуществ шаблона проектирования разделения чтения и записи
  • Производительность операции чтения очень высокая

Поскольку операции чтения не требуют получения блокировки, несколько потоков могут выполнять операции чтения одновременно, не мешая друг другу. Это делает операцию чтения CopyOnWriteArrayList очень хорошей в сценариях с высоким уровнем параллелизма.

  • согласованность данных

Поскольку запись выполняется путем копирования базового массива и внесения изменений в новый массив, исключается возможность одновременного изменения одного и того же элемента несколькими потоками. Это обеспечивает согласованность данных.

  • Подходит для сценариев, где больше читают и меньше пишут.

Поскольку операция записи требует копирования всего базового массива, производительность CopyOnWriteArrayList может сильно снизиться в сценариях, где операции записи выполняются часто. Но в сценариях, где больше читают, а меньше пишут, он может полностью раскрыть свои преимущества.

3.2 Существующие проблемы с производительностью
  • Использование памяти

Каждая операция записи требует копирования всего базового массива, что увеличивает объем памяти. Эти затраты памяти могут стать значительными, особенно если список велик.

  • Снижение производительности операций записи

Поскольку каждая операция записи требует копирования всего массива и внесения изменений в новый массив, производительность операции записи может существенно ухудшиться. Это снижение производительности может быть более очевидным, особенно в сценариях с высоким уровнем параллелизма.

  • Частый вывоз мусора

Поскольку операции записи создают новые массивы, они могут привести к частой сборке мусора. Это может повлиять на общую производительность системы.

В общем, CopyOnWriteArrayList — это потокобезопасная реализация списка, подходящая для сценариев, в которых требуется больше чтения и меньше записи. Он реализует разделение чтения и записи путем копирования базового массива, улучшая производительность одновременного выполнения операций чтения. Однако при их использовании вам необходимо идти на компромиссы и делать выбор на основе конкретных сценариев, чтобы избежать потенциальных проблем с производительностью.

3️⃣Сценарии использования CopyOnWriteArrayList

CopyOnWriteArrayListПодходит для сценариев, где больше читают и меньше писать.. В этом сценарии,Поскольку операция чтения не требует получения блокировки,Таким образом, возможности параллельных вычислений многоядерных процессоров могут быть полностью использованы.,Улучшите пропускную способность системы. Однако,В сценариях, где операции записи выполняются чаще,CopyOnWriteArrayListПроизводительность。

4️⃣Применение CopyOnWriteArrayList

поддаодининдивидуальныйиспользоватьCopyOnWriteArrayListкод,Он имитирует простую систему выпуска новостей. в этой системе,Несколько потоков могут работать одновременно новость и читайте список новостей. как операций чтения гораздо больше, чем операций записи.,Так что используйтеCopyOnWriteArrayListдаподходящий。

Язык кода:javascript
копировать
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

// Новости
class News {
    private String title;
    private String content;

    public News(String title, String content) {
        this.title = title;
        this.content = content;
    }

    public String getTitle() {
        return title;
    }

    public String getContent() {
        return content;
    }

    @Override
    public String toString() {
        return "News{" +
                "title='" + title + '\'' +
                ", content='" + content + '\'' +
                '}';
    }
}

// Класс системы выпуска новостей
public class NewsPublisherSystem {
    // Используйте CopyOnWriteArrayList для хранения списка новостей.
    private final List<News> newsList = new CopyOnWriteArrayList<>();

    // Добавить новость
    public void addNews(News news) {
        newsList.add(news);
        System.out.println("Добавлены новости: " + news);
    }

    // Получить список новостей
    public List<News> getNewsList() {
        return newsList;
    }

    // Имитация многопоточности для добавления и чтения новостей
    public void simulate() {
        ExecutorService executor = Executors.newFixedThreadPool(10);

        // представлять на рассмотрение5индивидуальный Добавить миссия новости
        for (int i = 0; i < 5; i++) {
            final int index = i;
            executor.submit(() -> {
                for (int j = 0; j < 10; j++) {
                    News news = new Новости("название новости" + index + "-" + j, «Новостной контент» + index + "-" + j);
                    addNews(news);
                    try {
                        // Имитация задержки пресс-релиза
                        TimeUnit.MILLISECONDS.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        // Отправьте 5 заданий, чтобы прочитать список новостей
        for (int i = 0; i < 5; i++) {
            executor.submit(() -> {
                for (int j = 0; j < 20; j++) {
                    System.out.println("Текущий список новостей: " + getNewsList());
                    try {
                        // Имитировать задержку чтения списка новостей
                        TimeUnit.MILLISECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }

        // Отключите службу исполнителя
        executor.shutdown();
        try {
            if (!executor.awaitTermination(1, TimeUnit.MINUTES)) {
                executor.shutdownNow();
            }
        } catch (InterruptedException e) {
            executor.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }

    public static void main(String[] args) {
        NewsPublisherSystem system = new NewsPublisherSystem();
        system.simulate();
    }
}

NewsPublisherSystem类维护ПонятноодининдивидуальныйCopyOnWriteArrayListдля хранения объектов новостей。addNewsМетод, используемый для Добавить новость в список,иgetNewsListМетод, используемый дляполучатькогда Предыдущий список новостей。

существоватьsimulateв методе,Мы создаем пул потоков фиксированного размера.,ипредставлять на рассмотрение Понятно10индивидуальный Задача:в5индивидуальный Задача用于Добавить новость,кроме того5индивидуальный Задача用于读取新闻列表。Каждыйиндивидуальный Добавить миссия новостивстреча创建и添加10новости,Каждая задача чтения списка новостей будет читать список новостей 20 раз.

из-за использованияCopyOnWriteArrayList,Несколько потоков могут читать список новостей одновременно,и Нетвстречаиметь Безопасность резьбывопрос。когда Добавить новостьчас,CopyOnWriteArrayListвстречакопироватьбазовый массив,Это гарантирует, что операции чтения не будут зависеть от операций записи.

пожалуйста, обрати внимание,потому чтоCopyOnWriteArrayListсуществоватьоперация записичасвстречакопироватьвсеиндивидуальныйбазовый массив,Поэтому, когда список новостей очень велик и операции записи выполняются часто,,Это может повлиять на производительность. в этом случае,Возможно, потребуется рассмотреть другие параллельные структуры данных или стратегии синхронизации. Однако,В этом случае,Поскольку операций чтения гораздо больше, чем операций записи.,использоватьCopyOnWriteArrayListдаподходящий。

5️⃣Резюме

CopyOnWriteArrayListдаJavaПараллельное программирование中одининдивидуальныйважный Безопасность Реализация списка потоков. Он реализует разделение чтения и записи через базовый массив, улучшая производительность одновременного выполнения операций чтения. Однако у него также есть некоторые потенциальные проблемы с производительностью, такие как Использование памяти Увеличивать、Снижение производительности операций записиа также Частый вывоз мусор. поэтому,существоватьиспользоватьCopyOnWriteArrayListчас,Взвешивание и выбор необходимо производить на основе конкретных сценариев использования. В сценарии больше читать и меньше писать,CopyOnWriteArrayListМожет хорошо работать;и В сценариях, где операции записи выполняются чаще,Возможно, необходимо принять во внимание и другие соображения.Безопасность Перечислите реализацию резьбы.


Навыки обновляются благодаря обмену ими, и каждый раз, когда я получаю новые знания, мое сердце переполняется радостью. Искренне приглашаем вас подписаться на публичный аккаунт код тридцать пять , для получения дополнительной технической информации.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose