CopyOnWrite, также известный как копирование при записи (COW), — это стратегия оптимизации в области программирования. Основная идея этой стратегии заключается в том, что когда несколько вызывающих объектов (или потоков) одновременно обращаются к одному и тому же ресурсу, они совместно получают указатель на ресурс. Пока ни один вызывающий объект не пытается изменить ресурс, все вызывающие могут продолжать получать доступ к одному и тому же ресурсу. Однако как только вызывающая сторона попытается изменить ресурс, система скопирует копию ресурса вызывающей стороне, а другие вызывающие стороны по-прежнему будут видеть исходный ресурс. Этот процесс прозрачен для других вызывающих сторон, которые не знают, что ресурс был скопирован.
В Java CopyOnWriteArrayList и CopyOnWriteArraySet — это два класса, использующие эту стратегию. Оба класса расположены в пакете java.util.concurrent и являются потокобезопасными классами коллекций. Когда элементы коллекции необходимо изменить, они не будут изменяться непосредственно в исходной коллекции, а будут копировать новую коллекцию, а затем изменять ее в новой коллекции. После завершения изменения укажите ссылку на исходную коллекцию на новую коллекцию. Такая конструкция позволяет выполнять операции чтения без блокировки, тем самым улучшая производительность параллелизма.
В общем, CopyOnWrite — это стратегия оптимизации, подходящая для сценариев, в которых требуется больше чтения и меньше записи. Она обеспечивает разделение чтения и записи за счет копирования данных, повышая производительность параллелизма. Однако у него также есть некоторые потенциальные проблемы с производительностью, такие как повышенное использование памяти, снижение производительности записи и частая сборка мусора. Поэтому при их использовании вам необходимо идти на компромиссы и делать выбор на основе конкретных сценариев.
CopyOnWriteArrayList
даJavaпараллельный пакетjava.util.concurrent
класс в,он достигList
интерфейс。как следует из названия,
CopyOnWriteArrayList — это класс Java, расположенный в пакете java.util.concurrent. Это поточно-ориентированный вариант ArrayList, в котором все изменяемые операции (такие как добавление, установка и т. д.) реализуются путем создания новой копии базового массива, отсюда и название списка «копирование при записи».
Поскольку CopyOnWriteArrayList не вносит никаких изменений в список при обходе,Поэтому он никогда не выкинетConcurrentModificationExceptionаномалия。это изменение операции(нравитьсяadd
、set
ждать)час,Будет копировать копию базового массива,Затем измените его в новом массиве,После завершения модификации переключите ссылку на базовый массив на новый массив. Такая конструкция позволяет выполнять операции чтения без блокировки.,тем самым улучшая производительность одновременного выполнения,Эта функция делает более безопасным выполнение операций обхода в многопоточной среде.
Однако в CopyOnWriteArrayList нет понятия «расширение». Каждая операция записи (например, добавление или удаление) требует копирования совершенно нового массива, что может вызвать проблемы с производительностью при частом выполнении операций записи, поскольку копирование всего массива занимает довольно много времени. Поэтому при использовании CopyOnWriteArrayList необходимо уделять особое внимание применимым сценариям. Вообще говоря, он больше подходит для сценариев, в которых требуется больше чтения и меньше записи.
CopyOnWriteArrayList — это потокобезопасный вариант ArrayList. Операции чтения могут выполняться без блокировки, что повышает производительность параллелизма.
В частности, CopyOnWriteArrayList имеет внутреннюю блокировку повторного входа (ReentrantLock) для обеспечения безопасности потоков, но эта блокировка используется только во время операций записи. При выполнении операции модификации поток сначала получает блокировку, затем копирует базовый массив и выполняет изменения в новом массиве. После завершения модификации убедитесь, что новый массив виден всем потокам через ссылку, измененную с помощью ключевого слова Летучий. Поскольку операции чтения не требуют получения блокировки, несколько потоков могут выполнять операции чтения одновременно, не мешая друг другу.
Поскольку операции чтения не требуют получения блокировки, несколько потоков могут выполнять операции чтения одновременно, не мешая друг другу. Это делает операцию чтения CopyOnWriteArrayList очень хорошей в сценариях с высоким уровнем параллелизма.
Поскольку запись выполняется путем копирования базового массива и внесения изменений в новый массив, исключается возможность одновременного изменения одного и того же элемента несколькими потоками. Это обеспечивает согласованность данных.
Поскольку операция записи требует копирования всего базового массива, производительность CopyOnWriteArrayList может сильно снизиться в сценариях, где операции записи выполняются часто. Но в сценариях, где больше читают, а меньше пишут, он может полностью раскрыть свои преимущества.
Каждая операция записи требует копирования всего базового массива, что увеличивает объем памяти. Эти затраты памяти могут стать значительными, особенно если список велик.
Поскольку каждая операция записи требует копирования всего массива и внесения изменений в новый массив, производительность операции записи может существенно ухудшиться. Это снижение производительности может быть более очевидным, особенно в сценариях с высоким уровнем параллелизма.
Поскольку операции записи создают новые массивы, они могут привести к частой сборке мусора. Это может повлиять на общую производительность системы.
В общем, CopyOnWriteArrayList — это потокобезопасная реализация списка, подходящая для сценариев, в которых требуется больше чтения и меньше записи. Он реализует разделение чтения и записи путем копирования базового массива, улучшая производительность одновременного выполнения операций чтения. Однако при их использовании вам необходимо идти на компромиссы и делать выбор на основе конкретных сценариев, чтобы избежать потенциальных проблем с производительностью.
CopyOnWriteArrayList
Подходит для сценариев, где больше читают и меньше писать.. В этом сценарии,Поскольку операция чтения не требует получения блокировки,Таким образом, возможности параллельных вычислений многоядерных процессоров могут быть полностью использованы.,Улучшите пропускную способность системы. Однако,В сценариях, где операции записи выполняются чаще,CopyOnWriteArrayList
Производительность。
поддаодининдивидуальныйиспользоватьCopyOnWriteArrayList
код,Он имитирует простую систему выпуска новостей. в этой системе,Несколько потоков могут работать одновременно новость и читайте список новостей. как операций чтения гораздо больше, чем операций записи.,Так что используйтеCopyOnWriteArrayList
даподходящий。
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
даподходящий。
CopyOnWriteArrayList
даJavaПараллельное программирование中одининдивидуальныйважный Безопасность Реализация списка потоков. Он реализует разделение чтения и записи через базовый массив, улучшая производительность одновременного выполнения операций чтения. Однако у него также есть некоторые потенциальные проблемы с производительностью, такие как Использование памяти Увеличивать、Снижение производительности операций записиа также Частый вывоз мусор. поэтому,существоватьиспользоватьCopyOnWriteArrayList
час,Взвешивание и выбор необходимо производить на основе конкретных сценариев использования. В сценарии больше читать и меньше писать,CopyOnWriteArrayList
Может хорошо работать;и В сценариях, где операции записи выполняются чаще,Возможно, необходимо принять во внимание и другие соображения.Безопасность Перечислите реализацию резьбы.
Навыки обновляются благодаря обмену ими, и каждый раз, когда я получаю новые знания, мое сердце переполняется радостью. Искренне приглашаем вас подписаться на публичный аккаунт 『
код тридцать пять
』 , для получения дополнительной технической информации.