我是靠谱客的博主 清新皮皮虾,最近开发中收集的这篇文章主要介绍JUC解决多线程集合线程不安全,以及ConcurrentModificationException(并发修改异常),觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
ArrayList线程不安全
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* list集合线程不安全
* add()为无锁状态,意味着每一个线程都可以在同一时间去抢夺add使用
* 这就会导致在同一时间,多个线程对同一地址进行写入数据,
* 并且在写的同时,还会有大批线程来读取数据,这就
* 会出现一个异常ConcurrentModificationException(并发修改异常)
*
*
* 解决方法 1
使用Vector 他是ArrayList的前生 使用的线程同步
* 解决方法2
使用Collections.synchronizedList(new ArrayList<>()); 将其转换为线程安全的集合
* 解决方法3
使用juc中的CopyOnWriteArrayList
读写分离技术
*/
public class ConcurrentListDemo {
public static void main(String[] args) {
List<Object> list = new CopyOnWriteArrayList();//Collections.synchronizedList(new ArrayList<>());//new ArrayList<>();
for (int i = 0; i < 30; i++) {
new Thread(()->{
list.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(list);
}).start();
}
//
list.add("123");
//
list.add("123");
//
list.add("123");
//
System.out.println(list);
}
}
HashSet线程不安全
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
/**
* set集合线程不安全 问题与list相同 没有线程同步
* HashSet的底层是HashMap
*但是CopyOnWriteArraySet的底层是使用CopyOnWriteArrayList<E>();
*return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :
*
addIfAbsent(e, snapshot);
*
以上代码去重
*
*
防止其他线程add
再去校验有无重复项
*
if (snapshot != current) {
*
// Optimize for lost race to another addXXX operation
*
int common = Math.min(snapshot.length, len);
*
for (int i = 0; i < common; i++)
*
if (current[i] != snapshot[i] && eq(e, current[i]))
*
return false;
*
if (indexOf(e, current, common, len) >= 0)
*
return false;
*
}
*
*
* public CopyOnWriteArraySet() {
*
al = new CopyOnWriteArrayList<E>();
*
}
*
*
* public HashSet() {
*
map = new HashMap<>();
*}
*
* public boolean add(E e) {
*
return map.put(e, PRESENT)==null;
添加的值是一个常量Object
* }
*
*
* 解决方法
* 1.Collections.synchronizedSet(new HashSet<>());
* 2.juc CopyOnWriteArraySet()
读写分离技术
*/
public class ConcurrentSetDemo {
public static void main(String[] args) {
Set set = new CopyOnWriteArraySet();//Collections.synchronizedSet(new HashSet<>());//new HashSet();
for (int i = 0; i < 30; i++) {
new Thread(()->{
set.add(UUID.randomUUID().toString());
System.out.println(set);
}).start();
}
}
}
HashMap线程不安全
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* HashMap 同样线程不安全
*
* HashMap 底层使用的 是 Node类型的数组
Node类型的链表 以及红黑树
* static class Node<K,V> implements Map.Entry<K,V> {
*
final int hash;
*
final K key;
*
V value;
*
Node<K,V> next;
*为单向链表
*
* 创建默认大小是 16
,负载系数(负载因子是0.75)
当单个链表长度达到8时会转换为红黑树
*
*
*
* Node<K,V>[] tab; Node<K,V> p; int n, i;
*
若表为空则初始化一个表,或者扩建表
*
if ((tab = table) == null || (n = tab.length) == 0)
*
n = (tab = resize()).length;
*
//将总长度减1(16-1)=15
与 hash(若为1) 做与运算
1111 & 0001 结果 为 0001
*
if ((p = tab[i = (n - 1) & hash]) == null) 从表中取值 若此索引为空
*
tab[i] = newNode(hash, key, value, null); //将数据添加到此索引
*
else {
//经过以上判断 若 p查到啦则走下面程序 (所以p有值)
*
Node<K,V> e; K k;
*
//判断若 p的hash值等于带添加的hash并且 key值相等
*
if (p.hash == hash &&
*
((k = p.key) == key || (key != null && key.equals(k))))
*
//则覆盖
*
e = p;
*
*
后面是对树的处理没有研究
*
*
*
* 解决线程不安全
*
* 方法1 : Collections.synchronizedMap(new HashMap<>())
* 方法2 : ConcurrentHashMap();
*/
public class ConcurrentMapDemo {
public static void main(String[] args) {
Map<Object, Object> hashMap = new ConcurrentHashMap<>();//Collections.synchronizedMap(new HashMap<>());//new HashMap<>();
for (int i = 0; i < 30; i++) {
new Thread(()->{
hashMap.put(UUID.randomUUID().toString(),"123");
System.out.println(hashMap);
}).start();
}
}
}
最后
以上就是清新皮皮虾为你收集整理的JUC解决多线程集合线程不安全,以及ConcurrentModificationException(并发修改异常)的全部内容,希望文章能够帮你解决JUC解决多线程集合线程不安全,以及ConcurrentModificationException(并发修改异常)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复