CopyOnWriteArraySet是CopyOnWriteArrayList类的弟弟。 这些是专用集合类,这些类是在JDK 1.5上添加的,以及它们最流行的表亲ConcurrentHashMap 。 它们是并发收集框架的一部分,位于java.util.concurrent包中。
CopyOnWriteArraySet最适合作为只读集合,其大小足够小,以便在发生某些变异操作时进行复制,例如,您可以在应用程序启动时使用CopyOnWriteArraySet来存储对象,并允许多个应用程序线程在应用程序生命周期中对其进行访问。 如果在此期间出现了新的条件或对象,也可以将其添加到此Set中,但会产生创建新数组的费用。 关于CopyOnWriteArraySet要了解的最重要的事情之一是它由CopyOnWriteArrayList支持,这意味着它还共享CopyOnWriteArrayList的所有基本属性。 要记住的另一件事是该集合类的迭代器不支持remove()操作,尝试在迭代时删除一个元素将导致UnSupportedOperationException。 这样做是为了确保遍历期间的速度,使用Iterator遍历此set实现的速度很快,并且不会遇到其他线程的干扰。 迭代器实际上在构造迭代器时依赖于不变的阵列快照。 简而言之,如果set足够小,可以在添加,设置或删除时进行复制,则使用CopyOnWriteArraySet,并且主要目的是读取偶尔更新的数据。 另外,如果要在迭代过程中删除元素,请不要使用此Set实现,因为它的迭代器不支持remove(),并抛出java.lang.UnsupportedOperationException,如下所示:
[RAJ] Event received : FOUR
Exception in thread "main" java.lang.UnsupportedOperationExceptionat java.util.concurrent.CopyOnWriteArrayList$COWIterator.remove(Unknown Source)at Publisher.notifySubs(HelloHP.java:43)at HelloHP.main(HelloHP.java:23)
这是我们完整的Java程序,展示了如何使用CopyOnWriteArraySet 。 在我们的示例中,我们使用发布者订阅者模式来演示其用法。 在启动过程中订阅的大多数订户,发布者的主要任务是对其进行迭代,并通知他们任何更新。 有时也可以添加和删除订户。 由于我们需要快速遍历,因此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一起添加。 这也是一个使用内部CopyOnWriteArrayList进行所有操作的Set。 因此,它具有该类的相同基本属性。 它不是SortedSet,因此在迭代过程中不能保证元素的顺序。
- CopyOnWriteArraySet最适合于集大小通常保持较小的应用程序,只读操作大大超过了可变操作,并且您需要防止遍历期间线程之间的干扰。
- CopyOnWriteArraySet的另一个好处是线程安全,它是一个并发集合 。
- 可变操作(添加,设置,删除等)非常昂贵,因为它们通常需要复制整个基础数组。
- 迭代器不支持可变删除操作。
- 通过迭代器的遍历速度很快,并且不会遇到其他线程的干扰。 迭代器在构造迭代器时依赖于数组的不变快照。
这就是如何在Java中使用CopyOnWriteArraySet的全部内容。 正如我所说的,它是CopyOnWriteArrayList的弟弟,因此,如果您了解其中之一,则可以使用其他方法。 两者唯一的区别是一个是List,另一个是Set,但这带来了Java中Set和List之间的所有区别 。 例如,列表是有序的,而Set是无序的则允许重复,但不允许重复。 始终记住,CopyOnWriteArraySet是一个特殊用途的Collection类,并且仅应在条件允许的情况下使用它,否则请坚持使用通用Set实施,例如HashSet,LinkedHashSet或同步的收集类。
翻译自: https://www.javacodegeeks.com/2014/06/how-to-use-copyonwritearrayset-in-java-with-example.html