集合类不安全
458字约2分钟
2024-08-08
CopyOnWriteArrayList
List 不是线程安全的
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
new Thread(() -> {
list.add(UUID.randomUUID().toString().substring(0, 5));
System.out.println(list);
}, String.valueOf(i)).start();
}
System.out.println(">>" + list);
}
并发执行下会出现 Exception in thread "8" java.util.ConcurrentModificationException
(并发修改异常)
解决方案
使用线程安全的
Vector
类,List<String> list = new Vector<>();
将
ArrayList
类转换为线程安全的,List<String> list = Collections.synchronizedList(new ArrayList<>());
使用
juc
包中的CopyOnWriteArrayList
,List<String> list = new CopyOnWriteArrayList<>();
CopyOnWriteArrayList 与 Vector 区别
/**
* Vector 类中方法加的 synchronized 锁,效率相对较低
* Appends the specified element to the end of this Vector.
*
* @param e element to be appended to this Vector
* @return {@code true} (as specified by {@link Collection#add})
* @since 1.2
*/
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
/**
* CopyOnWriteArrayList 采用 Lock 锁,写时复制
* Appends the specified element to the end of this list.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}
CopyOnWriteArraySet
Set 不是线程安全的
public static void main(String[] args) {
Set<String> set = new HashSet<>();
for (int i = 1; i <= 10; i++) {
new Thread(() -> {
set.add(UUID.randomUUID().toString().substring(0, 5));
System.out.println(set);
}, String.valueOf(i)).start();
}
}
并发执行下会出现 Exception in thread "3" java.util.ConcurrentModificationException
(并发修改异常)
解决方案
将
HashSet
类转换为线程安全的,Set<String> set = Collections.synchronizedSet(new HashSet<>());
使用
juc
包中的CopyOnWriteArraySet
Set<String> set = new CopyOnWriteArraySet<>();
ConcurrentHashMap
Map
不是线程安全的
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
for (int i = 1; i <= 30; i++) {
new Thread(() -> {
map.put(Thread.currentThread().getName(), UUID.randomUUID().toString().substring(0, 5));
System.out.println(map);
}, String.valueOf(i)).start();
}
}
并发执行下会出现 Exception in thread "16" Exception in thread "21" java.util.ConcurrentModificationException
(并发修改异常)
解决方案
将
map
转为线程安全的,Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
使用
juc
包中的ConcurrentHashMap
,Map<String, String> map = new ConcurrentHashMap<>();