当前位置: 首页 > news >正文

如何在多线程环境下避免快速失败异常?

在多线程环境下,可通过以下几种方式避免快速失败(Fail-Fast)异常:

1. 使用线程安全的集合类

Java 提供了多种线程安全的集合类,它们在迭代时不会抛出 ConcurrentModificationException

示例:使用 CopyOnWriteArrayList

java

import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;public class CopyOnWriteExample {public static void main(String[] args) {List<String> list = new CopyOnWriteArrayList<>();list.add("apple");list.add("banana");// 线程 1:遍历集合Thread t1 = new Thread(() -> {Iterator<String> it = list.iterator();while (it.hasNext()) {System.out.println(it.next());try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}});// 线程 2:修改集合Thread t2 = new Thread(() -> {try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}list.add("cherry"); // 不会触发异常});t1.start();t2.start();}
}
常用线程安全集合
  • CopyOnWriteArrayList:适用于读多写少的场景,每次修改时会创建新数组。
  • ConcurrentHashMap:高效的线程安全 Map,支持并发读写。
  • ConcurrentLinkedQueue:无界线程安全队列,基于链表实现。

2. 使用同步机制

通过显式的同步(如 synchronized 块或 ReentrantLock)来保证同一时间只有一个线程访问集合。

示例:使用 synchronized 块

java

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;public class SynchronizedListExample {private static final List<String> list = new ArrayList<>();private static final Object lock = new Object();public static void main(String[] args) {list.add("apple");list.add("banana");// 线程 1:遍历集合Thread t1 = new Thread(() -> {synchronized (lock) {Iterator<String> it = list.iterator();while (it.hasNext()) {System.out.println(it.next());}}});// 线程 2:修改集合Thread t2 = new Thread(() -> {synchronized (lock) {list.add("cherry");}});t1.start();t2.start();}
}
注意事项
  • 同步会导致性能下降,尤其在读操作频繁时。
  • 需要确保所有对集合的访问都使用相同的锁。

3. 使用 Collections.synchronizedList() 包装集合

将普通集合转换为同步集合,但迭代时仍需手动同步。

示例:

java

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;public class SynchronizedWrapperExample {public static void main(String[] args) {List<String> list = Collections.synchronizedList(new ArrayList<>());list.add("apple");list.add("banana");// 迭代时必须手动同步synchronized (list) {Iterator<String> it = list.iterator();while (it.hasNext()) {System.out.println(it.next());}}// 修改操作会自动同步list.add("cherry");}
}

4. 使用并发友好的迭代方式

某些并发集合提供了弱一致性(Weakly Consistent)的迭代器,允许在迭代过程中修改集合。

示例:ConcurrentHashMap 的弱一致性迭代器

java

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;public class ConcurrentHashMapExample {public static void main(String[] args) {ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();map.put("apple", 1);map.put("banana", 2);// 弱一致性迭代器允许并发修改Iterator<String> it = map.keySet().iterator();while (it.hasNext()) {String key = it.next();System.out.println(key);map.put("cherry", 3); // 不会抛出异常}}
}

根据具体业务场景选择合适的方案,优先考虑使用 Java 提供的并发集合类,避免手动同步带来的复杂性。

相关文章:

  • GPU异步执行漏洞攻防实战:从CUDA Stream竞争到安全编程规范
  • NHANES指标推荐:OBS
  • 大数据架构选型分析
  • 深度学习中的提示词优化:梯度下降全解析
  • 前端缓存策略
  • Milvus(23):过滤
  • 中国近代史2
  • 工业场景轮式巡检机器人纯视觉识别导航的优势剖析与前景展望
  • uniapp 弹窗封装(上、下、左、右、中五个方位)
  • 【FFmpeg+SDL】使用FFmpeg捕获屏幕,SDL显示
  • win10下安装redis并设置开机自启动
  • 前端的面试笔记——JavaScript篇(二)
  • 口播视频怎么剪!利用AI提高口播视频剪辑效率并增强”网感”
  • MATLAB安装全攻略:常见问题与解决方案
  • Linux | Linux系统安装虚拟机教程(超级简单)
  • 以项目的方式学QT开发(一)——超详细讲解(120000多字详细讲解,涵盖qt大量知识)逐步更新!
  • 比亚迪跨界降维打击!将正式宣布跨界,进入两三轮电动车电池市场
  • 解决xxx.jar中没有主清单属性的问题
  • ubuntu18 设置静态ip
  • Milvus Docker 部署教程
  • 30平米的无障碍酒吧里,我们将偏见折叠又摊开
  • 山西临汾哪吒主题景区回应雕塑被指抄袭:造型由第三方公司设计
  • GDP逼近五千亿,向海图强,对接京津,沧州剑指沿海经济强市
  • 吉林:消纳绿电,“氢”装上阵
  • 言短意长|西湖大学首次“走出西湖”
  • 三大股份制银行入局AIC,一级市场再迎“活水”