Java集合解决线程安全问题


一、ArrayList线程安全问题

1、ArrayList例子

List<String> strings = new ArrayList<>();
//3个线程运行
for (int i=0;i<30;i++)
{
new Thread(()->{
strings.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(strings);
},String.valueOf(i)).start();
}

故障问题,导致原因,如何修改,优化建议
 1、故障问题:java.util.ConcurrentModificationException
 2、导致原因:并发争抢修改导致 ,一个人在写,另一个在抢,会造成数据不一致。 list出现异常和线程不安全,出现null

2、解决方法

1、如何修改,使用Collections工具类
//使用辅助工具类
List<String> stringsColl = Collections.synchronizedList(new ArrayList<String>());
for (int i=0;i<30;i++)
{
new Thread(()->{
stringsColl.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(stringsColl);
},String.valueOf(i)).start();
}
2、写实复制,读写分离,优化,解决并发

内部用了lock锁加锁后复制新数组并将数组加一再写回去,set进集合里

List<String> objects = new CopyOnWriteArrayList<>();
for (int i=0;i<30;i++)
{
new Thread(()->{
objects.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(objects);
},String.valueOf(i)).start();
}
CopyOnWriteArrayList内部======
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();
	}
}
======================

二、HashSet的解决线程安全

1、解决方法

1、使用Collections
/**
* 一解决
*/
Set<String> strings = Collections.synchronizedSet(new HashSet<String>());
for (int i=0;i<30;i++) {
new Thread(()->{
strings.add(UUID.randomUUID().toString().substring(0,8));
System.out.println(strings);
},String.valueOf(i)).start();
}
2、使用CopyOnWriteArraySet
/**
* 二优化,hashSet一个参入得是key,value为写死的final Object
*/
Set copyOnWriteArraySet = new CopyOnWriteArraySet();
for (int i=0;i<30;i++) {
	new Thread(()->{
	copyOnWriteArraySet.add(UUID.randomUUID().toString().substring(0,8));
	System.out.println(copyOnWriteArraySet);
	},String.valueOf(i)).start();
}

三、解决hashMap线程不安全

1、解决方法Collections

效率不高,锁太重

//性能太低
Map<String, Object> stringObjectMap = Collections.synchronizedMap(new HashMap<String, Object>());

2、使用ConcurrentHashMap

原理:jdk1.8中抛弃了segment的段锁,只保留segment的结构,而是直接用Node数组+链表+红黑树的数据结构来实现,并发控制使用Synchronized和CAS(自旋)来操作

Map<String, Object> concurrentHashMap = new ConcurrentHashMap<>();

3、线程安全,有序,查询快的集合

跳表遍历
ConcurrentSkipListSet 基于ConcurrentSkipListMap
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会改bug的程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值