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

东莞销售网站公司哪家好宁德seo

东莞销售网站公司哪家好,宁德seo,二维码生成器在线制作图片加文字,seo专业培训技术在对一些非并发集合同时进行读写的时候,会抛出 ConcurrentModificationException 异常产生示例 示例一(单线程): 遍历集合时候去修改 抛出 ConcurrentModificationException 的主要原因是当你在遍历一个集合(如 Map…

在对一些非并发集合同时进行读写的时候,会抛出 ConcurrentModificationException

异常产生示例

示例一(单线程): 遍历集合时候去修改

抛出 ConcurrentModificationException 的主要原因是当你在遍历一个集合(如 Map、List 或 Set)时,同时对该集合进行了结构性修改(例如添加或删除元素),而这些修改没有通过迭代器自身的相应方法进行。

    private static Map<String, String> map = new HashMap<>();static {for (int i = 0; i < 100000; i++) {map.put(String.valueOf(i), String.valueOf(i));}}public static void main(String[] args) {// 在循环的时候删除元素map.forEach((key, value) -> {if (Integer.parseInt(key) % 2 == 0){map.remove(key);return;}System.out.println(key + value);});}

示例二(多线程): 多线程读写

多线程读写和示例一抛出异常的原因一样

 private static Map<String, String> map = new HashMap<>();static {for (int i = 0; i < 100000; i++) {map.put(String.valueOf(i), String.valueOf(i));}}public static void main(String[] args) {// 并发修改 map 让其出现并发异常for (int i = 0; i < 100; i++) {new Thread(new Add(map)).start();new Thread(new Read(map)).start();}}static class Add implements Runnable {private HashMap<String, String> map;public Add(HashMap<String, String> map) {this.map = map;}@Overridepublic void run() {map.clear();for (int i = 0; i < 100000; i++) {map.put(String.valueOf(i), String.valueOf(i));}}}static class Read implements Runnable {private HashMap<String, String> map;public Read(HashMap<String, String> map) {this.map = map;}@Overridepublic void run() {CopyOnWriteArraySet<Map.Entry<String,String>> copyOnWriteArraySet = new CopyOnWriteArraySet<>(map.entrySet());for (int i = 0; i < 100000; i++) {copyOnWriteArraySet.forEach((entry) -> {String a = entry.getKey() + entry.getValue();});}}}

解决问题

解决示例一

  1. CopyOnWriteArraySet

CopyOnWriteArraySet 是 Java 并发集合包中的一种线程安全的集合。它的关键特性在于“写时复制”(copy-on-write),这意味着在对集合进行修改操作(如添加或删除元素)时,其实现机制是创建底层数组的一个新副本,而不是直接在原数组上进行修改。这种机制使得在遍历 CopyOnWriteArraySet 时不会抛出 ConcurrentModificationException,因为迭代器是在数组的一个快照上工作的,它不受后续对集合进行的修改的影响。

CopyOnWriteArraySet<Map.Entry<String,String>> copyOnWriteArraySet = new CopyOnWriteArraySet<>(map.entrySet());
copyOnWriteArraySet.forEach((entry) -> {String key = entry.getKey();String value = entry.getValue();if (Integer.parseInt(key) % 2 == 0){map.remove(key);return;}System.out.println(key + value);
});
  1. 迭代器

当使用迭代器遍历集合时,直接调用集合的 remove 方法(如 map.remove(key))会导致 ConcurrentModificationException,因为这破坏了迭代器预期的遍历顺序。而迭代器自身提供的 remove 方法是唯一一种可以在遍历过程中安全移除元素的方法。该方法确保了在删除元素后,迭代器能够继续正确地跟踪集合的状态,不会导致并发修改异常。

Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {Map.Entry<String, String> entry = iterator.next();if (Integer.parseInt(entry.getKey()) % 2 == 0) {iterator.remove(); // 使用迭代器的remove方法来安全地移除元素} else {System.out.println(entry.getKey() + entry.getValue());}
}
  1. 替换原本的集合
map = map.entrySet().stream().filter(entry -> Integer.parseInt(entry.getKey()) % 2 != 0).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v1, HashMap::new));
  1. 包装map
ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>(map);
concurrentHashMap.forEach((key, value) -> {if (Integer.parseInt(key) % 2 == 0){map.remove(key);return;}System.out.println(key + value);
});

方式二,也是替换 Map

ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>(map);
concurrentHashMap.forEach((key, value) -> {if (Integer.parseInt(key) % 2 == 0){concurrentHashMap .remove(key);return;}System.out.println(key + value);
});
map = concurrentHashMap 
  1. 使用 removeIf
 map.entrySet().removeIf(f-> Integer.parseInt(f.getKey()) % 2 == 0);

解决示例二

HashMap 本身并不是线程安全的,最直接有效的方法是直接还一个线程安全的集合
Java 提供了多种线程安全的集合,它们主要通过不同的方式来支持并发操作。以下是一些常见的线程安全集合:


1. 基于 java.util.concurrent 包的线程安全集合

这些集合在高并发场景下性能较好,适用于大多数现代应用。

1.1 ConcurrentHashMap
  • 特性:线程安全的哈希表,支持高效的并发读写。
  • 优势:读操作无锁,写操作基于分段锁(Java 8 后使用 CAS)。
  • 用法:
    ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
    
1.2 CopyOnWriteArrayList
  • 特性:在写操作时复制整个底层数组,因此适合读多写少的场景。
  • 优势:读操作无锁,写操作创建新数组,避免并发问题。
  • 用法:
    CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
    
1.3 CopyOnWriteArraySet
  • 特性:基于 CopyOnWriteArrayList 实现,适合高频读取、低频修改的场景。
  • 用法:
    CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<>();
    
1.4 ConcurrentLinkedQueue
  • 特性:基于链表的无界非阻塞线程安全队列。
  • 优势:采用 CAS 操作,适合高并发环境下的队列操作。
  • 用法:
    ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
    
1.5 ConcurrentLinkedDeque
  • 特性:双端队列版本的 ConcurrentLinkedQueue,支持高效的双向操作。
  • 用法:
    ConcurrentLinkedDeque<String> deque = new ConcurrentLinkedDeque<>();
    
1.6 LinkedBlockingQueue
  • 特性:基于链表的阻塞队列,支持可选的容量限制。
  • 优势:适合生产者-消费者模型。
  • 用法:
    LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>(100);
    
1.7 LinkedBlockingDeque
  • 特性:双端队列版本的 LinkedBlockingQueue,支持从两端进行操作。
  • 用法:
    LinkedBlockingDeque<String> deque = new LinkedBlockingDeque<>(100);
    
1.8 ConcurrentSkipListMap
  • 特性:基于跳表的线程安全 SortedMap 实现,支持按键排序。
  • 用法:
    ConcurrentSkipListMap<String, String> map = new ConcurrentSkipListMap<>();
    
1.9 ConcurrentSkipListSet
  • 特性:基于 ConcurrentSkipListMap 实现的线程安全有序集合。
  • 用法:
    ConcurrentSkipListSet<String> set = new ConcurrentSkipListSet<>();
    

2. 基于 Collections 工具类的同步集合

Collections.synchronizedXXX 方法可以将非线程安全的集合包装成线程安全集合,但性能不如 java.util.concurrent 包。

2.1 SynchronizedList
  • 特性:将普通 List 包装成线程安全集合。
  • 用法:
    List<String> list = Collections.synchronizedList(new ArrayList<>());
    
2.2 SynchronizedSet
  • 特性:将普通 Set 包装成线程安全集合。
  • 用法:
    Set<String> set = Collections.synchronizedSet(new HashSet<>());
    
2.3 SynchronizedMap
  • 特性:将普通 Map 包装成线程安全集合。
  • 用法:
    Map<String, String> map = Collections.synchronizedMap(new HashMap<>());
    

注意:使用 Collections.synchronizedXXX 包装的集合在迭代时需要显式加锁:

synchronized (list) {for (String s : list) {// 操作}
}

3. Immutable Collections(不可变集合)

Java 9 引入了不可变集合,通过 List.of()Set.of()Map.of() 创建:

  • 特性:线程安全,不可修改,适合配置类或常量类数据。
  • 用法:
    List<String> list = List.of("a", "b", "c");
    Set<String> set = Set.of("a", "b", "c");
    Map<String, String> map = Map.of("key1", "value1", "key2", "value2");
    

4. Vector 和 Stack

这些是早期的线程安全集合:

  • Vector:线程安全的 List 实现。
    Vector<String> vector = new Vector<>();
    
  • Stack:线程安全的栈(继承自 Vector)。
    Stack<String> stack = new Stack<>();
    

但它们性能较低,通常不推荐使用。


推荐选择

  1. 高并发场景:优先使用 java.util.concurrent 包下的集合,例如 ConcurrentHashMapCopyOnWriteArrayListCopyOnWriteArraySet等。
  2. 读多写少:使用 CopyOnWriteArrayListCopyOnWriteArraySet
  3. 简易同步:使用 Collections.synchronizedXXX 包装集合。
  4. 不可修改数据:使用不可变集合(List.of 等)。

如果你有特定的应用场景,可以详细讨论选择最优集合!

http://www.dinnco.com/news/10112.html

相关文章:

  • web网站建设一题库陕西seo排名
  • 数字货币网站开发软文优化
  • 论述电子商务网站的建设艺考培训
  • 在互易上做的网站如何修改论坛seo网站
  • 微小店适合卖做分类网站吗软文写作什么意思
  • 网站建设利益分析实时热榜
  • wordpress文本插件seo百度站长工具查询
  • 四川专业旅游网站制作苏州seo公司
  • wordpress暴力破解seo视频教程汇总
  • wordpress 缩略图类型知乎seo
  • 网站怎么建设上海百度移动关键词排名优化
  • 网站建设中的思想和算法近三年成功的营销案例
  • h5case 网站百度代理合作平台
  • 音乐网站怎么做社交的营销宣传方式有哪些
  • 章丘哪里做网站衡水seo培训
  • 做党政板报的网站北京发生大事了
  • 组建网站开发团队房地产营销策略有哪些
  • 数据库 网站开发所需流程免费优化推广网站的软件
  • 丰台网站建设联系方式aso关键词覆盖优化
  • 网上购物商城网站建设毕业设计百度搜索引擎营销
  • 网站建设linux快手seo软件下载
  • 网站备案密码 多少位百度快照客服
  • 企业网站哪个好百度客服中心
  • 一台vps可以做几个网站手机百度极速版app下载安装
  • 什么是wordpress主题武汉网络推广seo
  • 企业网站开发多少钱seo搜索引擎入门教程
  • 做一个购物网页优化网站的目的
  • php网站开发软件是什么潍坊seo教程
  • 小语种网站案例郑州网站关键词优化公司哪家好
  • 找网站建设企业某网站seo诊断分析