JUC高并发编程
五、集合的线程安全
5.2)HashSet集合线程
5.2.1)HashSet集合线程不安全案例展示
代码如下:
// HashSet集合线程不安全案例展示
public class HashSetErrorDemo {
public static void main(String[] args) {
//演示Hashset
Set<String> set = new HashSet<>();
for (int i = 0; i < 30; i++) {
new Thread(() -> {
//向集合添加内容
set.add(UUID.randomUUID().toString().substring(0, 8));
//从集合获取内容
System.out.println(set);
}, String.valueOf(i)).start();
}
}
}
输出:
java.util.ConcurrentModificationException at java.util.HashMapKeyIterator.next(HashMap.java:1469) at java.util.AbstractCollection.toString(AbstractCollection.java:461) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at com.study.collection.HashSetErrorDemo.lambda0(HashSetErrorDemo.java:25) at java.lang.Thread.run(Thread.java:748) java.util.ConcurrentModificationException at java.util.HashMapKeyIterator.next(HashMap.java:1469) at java.util.AbstractCollection.toString(AbstractCollection.java:461) at java.lang.String.valueOf(String.java:2994) at java.io.PrintStream.println(PrintStream.java:821) at com.study.collection.HashSetErrorDemo.lambda0(HashSetErrorDemo.java:25) at java.lang.Thread.run(Thread.java:748)
发现报错,java.util.ConcurrentModificationException ——》并发修改异常
问题: 为什么会出现并发修改异常?
查看HashSet的add方法源码 ,如下:
/**
* Adds the specified element to this set if it is not already present.
* More formally, adds the specified element <tt>e</tt> to this set if
* this set contains no element <tt>e2</tt> such that
* <tt>(e==null ? e2==null : e.equals(e2))</tt>.
* If this set already contains the element, the call leaves the set
* unchanged and returns <tt>false</tt>.
*
* @param e element to be added to this set
* @return <tt>true</tt> if this set did not already contain the specified
* element
*/
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
add() 方法没有添加 synchronized 关键字,即没有对多线程情况进行处理
5.2.2)HashSet集合线程不安全解决方案
5.2.2.1)解决方案-CopyOnWriteArraySet
使用 CopyOnWriteArraySet解决HashSet集合线程不安全问题,代码如下:
// CopyOnWriteArray解决HashSet集合线程不安全问题
public class CopyOnWriteArraySetDemo {
public static void main(String[] args) {
//演示Hashset
Set<String> set =