1.迭代器的问题

无论是直接迭代还是for-each循环(for-each内部也是用迭代器实现)语句,对容器迭代的标准方式都是Iterator。但是,即使是使用迭代器,也无法避免在迭代器在迭代期间对容器加锁。这是因为设计同步容器的迭代器时并没有考虑并发修改的问题。

它们表现出的行为是及时失败的,也就是容器在迭代的过程中如果被修改,就会抛出ConcurrentModificationException失败。
例如:

List<Integer> lists = new ArrayList<>();
lists.add(1);
lists.add(2);
for(Integer i : lists){System.out.println(i);
}

问题:上面这样做在其他线程进行修改时,容易出现ConcurrentModificationException,因此必须要在迭代过程中使用锁。

List<Integer> lists = new ArrayList<>();
lists.add(1);
lists.add(2);
synchronized(lists){for(Integer i : lists){System.out.println(i);}
}

问题:如果容器规模很大,或者每个元素执行操作的时间很长,那么修改线程就会进入长时间的等待。即使不存在饥饿或者死锁的问题,长时间对容器加锁也会降低程序的可伸缩性。持有的时间越长,那么在锁上的竞争就会越激烈,如果许多的线程都在等待锁,那么就会极大地降低吞吐量和CPU的利用率。

解决方法:
如果不希望迭代的时候对容器加锁,那么一个可替代的方法就是“克隆”容器,并在副本中进行迭代,这个方法保证迭代的数据都是修改前的数据。
但是问题是克隆容器会存在性能开销。

2.隐藏迭代器的问题

例如:

List<Integer> lists = new ArrayList<>();
for(int i = 0 ; i < 10 ; i++){list.add(1);
}
System.out.print(list);//容易出现同步问题

输出ArrayList会调用他的toString方法,而调用toString方法将使用迭代器,可能会抛出ConcurrentModificationException问题。

容器的hashCode,equal,containsAll,removeAll和retainAIl等方法,都会对容器进行迭代,抛出ConcurrentModificationException。

Java多线程之迭代器问题(四)相关推荐

  1. Java多线程学习之路(四)---死锁(DeadLock)

    Java多线程学习之路(四)-死锁(DeadLock) 1.定义 死锁就是多个线程在竞争共享资源的时候,相互阻塞,不能脱身的状态(个人理解).其实死锁一定程度上可以看成一个死循环. 举个现实生活中的例 ...

  2. Java 多线程详解(四)------生产者和消费者

    Java 多线程详解(一)------概念的引入:https://blog.csdn.net/weixin_39816740/article/details/80089790 Java 多线程详解(二 ...

  3. Java多线程学习二十四:阻塞队列包含哪些常用的方法?add、offer、put 等方法的区别?

    阻塞队列包含哪些常用的方法,以及 add,offer,put 等方法的区别. 在阻塞队列中有很多方法,而且它们都非常相似,所以非常有必要对这些类似的方法进行辨析,所以本课时会用分类的方式,和你一起,把 ...

  4. Java多线程学习三十四:使用 Future 有哪些注意点?Future 产生新的线程了吗

    Future 的注意点 1. 当 for 循环批量获取 Future 的结果时容易 block,get 方法调用时应使用 timeout 限制 对于 Future 而言,第一个注意点就是,当 for ...

  5. Java 多线程详解(五)------线程的声明周期

    Java 多线程详解(一)------概念的引入:https://blog.csdn.net/weixin_39816740/article/details/80089790 Java 多线程详解(二 ...

  6. 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)

    在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...

  7. Java多线程闲聊(四):阻塞队列与线程池原理

    Java多线程闲聊(四)-阻塞队列与线程池原理 前言 复用永远是人们永恒的主题,这能让我们更好地避免重复制造轮子. 说到多线程,果然还是绕不开线程池,那就来聊聊吧. 人们往往相信,世界是存在一些规律的 ...

  8. java多线程系列(四)---ReentrantLock的使用

    Lock的使用 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我的理 ...

  9. JAVA多线程提高十四: 面试题

    前面针对多线程相关知识点进行了学习,那么我们来来看看常见的面试题: 1. 空中网面试题1 package com.kongzhongwang.interview; import java.util.c ...

最新文章

  1. OpenCV+python:读取图片和视频详细信息
  2. 【项目管理】聊聊项目管理几点实践和理解(2)
  3. SESSION存储于redis(CI3)
  4. 使用gui调试x86系统的汇编代码
  5. 信用卡申请被拒原因分析
  6. python自动化操作应用程序错误_web自动化中踩过的低级错误坑(python+selenium)
  7. sqlserver 分组合并列_哪个“三人组”是历史最强组合?数据显示最均衡组合令人意外...
  8. HTML5本地存储详解
  9. 高德天气 php,天气查询-API文档-开发指南-Web服务 API | 高德地图API
  10. java 局部内部类
  11. 安装java正在使用中_如何安装java,安装JDK,JAVA SE正在使用中,安装不了
  12. Python算法教程:强连通分量
  13. Android 回声消除
  14. matlab方程例子,Matlab求解超定方程组实例
  15. 异地驾驶证转入(+到期换证)——赞深圳交警!
  16. 聊天服务器项目报告,网络聊天室实现报告
  17. 京东如何建设基于云原生架构的监控 - 日志系统?
  18. 在Linux环境下通过百度网盘下载并安装matlab2017a
  19. 电影《小萝莉的猴神大叔》观后感
  20. 用c++实现贪吃蛇小游戏,初学者记录一下首次实现的经历,有超详细的思路与语法讲解,新手向

热门文章

  1. C++ POD(Plain Old Data)类型
  2. 【白话科普】10s 从零看懂 H5
  3. C++ 面向对象(一)继承:继承、对象切割、菱形继承、虚继承、继承与组合
  4. 一句话概括互联网巨头,简直不要太真实!哈哈哈哈哈哈哈哈哈
  5. VVC为什么首先在印度落地?
  6. 张军:围绕“WebRTC+AI+大数据”创新
  7. 腾讯天幕——联动生态,共享安全
  8. CentOS7系统上Kubernetes集群搭建
  9. Android插件框架VirtualAPK
  10. 芯片巨头英特尔放弃竞争迷你计算机市场