JavaRush /Java блог /Архив info.javarush /Как пользоваться CopyOnWriteArraySet в Java с примером (п...
Lam-lam
30 уровень

Как пользоваться CopyOnWriteArraySet в Java с примером (перевод)

Статья из группы Архив info.javarush
CopyOnWriteArraySet это младший брат класса CopyOnWriteArrayList. Это специализированный набор классов, добавленных в JDK 1.5 вместе с их более популярным двоюродным братом ConcurrentHashMap. Они являются частью concurrent collection framework и расположены в пакете java.util.concurrent. Как пользоваться CopyOnWriteArraySet в Java с примером (перевод) - 1CopyOnWriteArraySet лучше всего подходит для read-only коллекций, размер которых достаточно мал, чтобы их скопировать, если произойдут некоторые изменяющие операции. Например, вы можете использовать CopyOnWriteArraySet для хранения объекта при запуске приложения, и дать множеству других потоков доступ к этому объекту на протяжении жизненного цикла приложения. Если новое состояние или объект приходят в течение этого времени, он также может быть добавлен в этот Set, со стоимостью создания нового массива. Одна из самых важных вещей, которую стоит знать о CopyOnWriteArraySet это то, что он реализован при помощи CopyOnWriteArrayList. Это означает, что CopyOnWriteArraySet также разделяет все основные свойства CopyOnWriteArrayList. Еще одна важная вещь, которую стоит запомнить: итераторы этого класса коллекции не поддерживают операцию remove(). Попытка удалить элемент во время интегрирования приведет к выбросу UnsupportedOperationException. Это сделано чтобы гарантировать скорость во время обхода. Обход этой реализации Set, используя итератор, осуществляется достаточно быстро, и во время него исключены вмешательства других потоков. В своей работе итераторы опираются на моментальный снимок массива, который был сделан во время создания итератора. Короче говоря, используйте CopyOnWriteArraySet если set достаточно мал, чтобы копировать его при добавлении, задании значения или удалении объектов, и основной целью является чтение обновляемых от случая к случаю данных. Кроме того, если вы хотите удалить элементы во время итерации, не используйте эту реализацию, потому что ее итератор не поддерживает remove(), и бросает java.lang.UnsupportedOperationException, как показано ниже:

[RAJ] Event received : FOUR 
Exception in thread "main" java.lang.UnsupportedOperationException
    at java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(Unknown Source)
    at Publisher.notifySubs(HelloHP.java:43)
    at HelloHP.main(HelloHP.java:23)

CopyOnWriteArraySet пример на Java

Вот готовая программа на Java показывающая, как использовать CopyOnWriteArraySet. В нашем примере мы использовали шаблон проектирования "Издатель-подписчик" (англ. publisher-subscriber pattern), чтобы продемонстрировать его использование. Большинство подписчиков подписаны во время пуска приложения и главной задачей издателя является их перебор и уведомление о каких-либо обновлениях. Время от времени может случаться добавление и удаление подписчика . Так как нам нужен быстрый обход, CopyOnWriteArraySet является хорошим выбором, особенно в многопоточной среде, где один поток может добавить абонента, а другой поток обрабатывает обновления.

import java.util.Iterator;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * Java program to demonstrate how to use CopyOnWriteArraySet in Java. Remember,
 * CopyOnWriteArraySet doesn't support remove() operation.
 *
 * @author Javin Paul
 */
public class CopyOnWriteArraySetDemo{

    public static void main(String args[]) {
        Publisher cricNext = new Publisher();

        SubScriber raj = new SubScriber("RAJ");
        SubScriber adom = new SubScriber("ADOM");

        cricNext.addSubscriber(raj);
        cricNext.addSubscriber(adom);

        cricNext.notifySubs("FOUR");
        cricNext.notifySubs("SIX");

    }

}

class Publisher {

    private CopyOnWriteArraySet setOfSubs = new CopyOnWriteArraySet();

    public void addSubscriber(SubScriber sub) {
        setOfSubs.add(sub);
    }

    public void notifySubs(String score) {
        Iterator itr = setOfSubs.iterator();
        while (itr.hasNext()) {
            SubScriber sub = itr.next();
            sub.receive(score);

            //itr.remove(); // not allowed, throws UnsupportedOperationException
        }
    }
}

class SubScriber {

    private String _name;

    public SubScriber(String name) {
        this._name = name;
    }

    public void receive(String score) {
        System.out.printf("[%s] Event received : %s %n", _name, score);
    }
}
Output:

[RAJ] Event received : FOUR 
[ADOM] Event received : FOUR 
[RAJ] Event received : SIX
[ADOM]Event received : SIX

Что нужно запомнить

CopyOnWriteArraySet реализует интерфейсы Collection и Set, а также, добавленный в JDK 1.5, вместе с другой специальной реализацией Set'а, EnumSet. Это также Set, который использует внутренний CopyOnWriteArrayList для всех своих операций. Таким образом, он разделяет те же основные свойства этого класса. Так как это не SortedSet, порядок элементов не гарантируется в течение итерации. Как пользоваться CopyOnWriteArraySet в Java с примером (перевод) - 2
  1. CopyOnWriteArraySet лучше всего подходит для приложений, в которых:

    • Размеры Set'ов, как правило остаются небольшими.
    • Операции read-only значительно превосходят операции, изменяющие объекты.
    • Вы должны предотвратить помехи между потоками во время обхода Set'а.
  2. Еще одним преимуществом CopyOnWriteArraySet является потокобезопасность. Эта коллекция поддерживает параллелизм.
  3. Мутативные операции (добавление, изменение, удаление и т.д.) являются дорогостоящими, так как они, как правило, требуют копирования всего базового массива.
  4. Итераторы не поддерживают мутативную операцию удаления.
  5. Обход используя итератор достаточно быстр и во время него исключены вмешательства других потоков. В своей работе итераторы опираются на моментальный снимок массива, который был сделан во время создания итератора.
На этом все об использовании CopyOnWriteArraySet в Java. Как я сказал, он является младшим братом CopyOnWriteArrayList. Так что если вы понимаете хотя бы один из них, то сможете использовать и другой. Единственное отличие в том, что один является List'ом а другой Set'ом, таким образом это влечет за собой унаследование всех отличий между этими структурами данных в Java. Например, в List важен порядок расположения элементов, и он может содержать дубликаты. В то время как Set является неупорядоченным, но не позволяет дублирование объектов. Всегда помните, что CopyOnWriteArraySet это специализированный Collection класс. Его стоит использовать только когда условия являются благоприятными. В любом другом случае можно пользоваться реализациями общего назначения. Например, HashSet, LinkedHashSet или синхронизированными классами коллекций. Оригинал: How to use CopyOnWriteArraySet in Java with Example
Комментарии (2)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Lam-lam Уровень 30
14 января 2016
Мой первый перевод. Всяческая критика приветствуется! :)