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

并发工具类库使用的常见问题

一、ThreadLocal在多线程环境中没有清理

由于ThreadLocal是和线程绑定的,如果线程被复用了,也即使用了线程池,那么ThreadLocal中的值是可能被复用的,这个特性如果是开发者没有预料到的,那么会产生很大的问题。例如,在JAVA web应用中,我们通常会使用很多ThreadLocal来保存一次请求的不同上下文信息,其中就包含登录用户,如果一次请求完成后,没有清理掉当前登录用户信息,那么当另外一个用户的请求进来,就会使用上一个用户,如果是涉及到数据写入,将直接导致数据错乱,造成严重生产问题。

二、ConcurrentHashMap使用的问题

ConcurrentHashMap提供的能力是保证单个操作在多线程环境下是安全的。如果有一段逻辑是先读取size大小,在决定是否往map里put(),那么这段逻辑必然产生并发问题。因为错误理解的ConcurrentHashMap的能力。解决办法是用加锁的方式控制并发。

三、CopyOnWriteArrayList使用的问题

CopyOnWrite 是一个常用的技术,Linux、Redis中都用到了。在 Java 中,CopyOnWriteArrayList 虽然是一个线程安全的 ArrayList,但因为其实现方式是,每次修改数据时都会复制一份数据出来,所以有明显的适用场景,即读多写少或者说希望无锁读的场景。

//测试并发写的性能
@GetMapping("write")
public Map testWrite() {
List<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
StopWatch stopWatch = new StopWatch();
int loopCount = 100000;
stopWatch.start("Write:copyOnWriteArrayList");
//循环100000次并发往CopyOnWriteArrayList写入随机元素
IntStream.rangeClosed(1, loopCount).parallel().forEach(__ -> copyOnWriteArrayList.add(ThreadLocalRandom.current().nextInt(loopCount)));
stopWatch.stop();
stopWatch.start("Write:synchronizedList");
//循环100000次并发往加锁的ArrayList写入随机元素
IntStream.rangeClosed(1, loopCount).parallel().forEach(__ -> synchronizedList.add(ThreadLocalRandom.current().nextInt(loopCount)));
stopWatch.stop();
log.info(stopWatch.prettyPrint());
Map result = new HashMap();
result.put("copyOnWriteArrayList", copyOnWriteArrayList.size());
result.put("synchronizedList", synchronizedList.size());
return result;
}//帮助方法用来填充List
private void addAll(List<Integer> list) {
list.addAll(IntStream.rangeClosed(1, 1000000).boxed().collect(Collectors.toList()));
}//测试并发读的性能
@GetMapping("read")
public Map testRead() {
//创建两个测试对象
List<Integer> copyOnWriteArrayList = new CopyOnWriteArrayList<>();
List<Integer> synchronizedList = Collections.synchronizedList(new ArrayList<>());
//填充数据
addAll(copyOnWriteArrayList);
addAll(synchronizedList);
StopWatch stopWatch = new StopWatch();
int loopCount = 1000000;
int count = copyOnWriteArrayList.size();
stopWatch.start("Read:copyOnWriteArrayList");
//循环1000000次并发从CopyOnWriteArrayList随机查询元素
IntStream.rangeClosed(1, loopCount).parallel().forEach(__ -> copyOnWriteArrayList.get(ThreadLocalRandom.current().nextInt(count)));
stopWatch.stop();
stopWatch.start("Read:synchronizedList");
//循环1000000次并发从加锁的ArrayList随机查询元素
IntStream.range(0, loopCount).parallel().forEach(__ -> synchronizedList.get(ThreadLocalRandom.current().nextInt(count)));
stopWatch.stop();
log.info(stopWatch.prettyPrint());
Map result = new HashMap();
result.put("copyOnWriteArrayList", copyOnWriteArrayList.size());
result.put("synchronizedList", synchronizedList.size());
return result;
}

http://www.lryc.cn/news/185285.html

相关文章:

  • GD32F10X ----RTC
  • 使用UiPath和AA构建的解决方案 1. 机器人过程自动化入门
  • rust字面量
  • Unix Network Programming Episode 79
  • Cesium展示——wkt 数据绘制
  • 打造完美家庭空间,让生活更加舒适
  • 解决loadDep:omelette: sill install loadAllDepsIntoIdealTree
  • 【深蓝学院】手写VIO第2章--IMU传感器--作业
  • Android多线程学习:线程
  • canvas 入门
  • 建议收藏!混迹职场多年总结出的8大技巧!
  • OpenCV4(C++)—— 视频和摄像头的加载、显示与保存
  • excel功能区(ribbonx)编程笔记6-box的使用
  • oralce配置访问白名单的方法
  • ToBeWritten之让响应团队参与并做好沟通
  • ffmpeg ts 关于av_seek_frame
  • 【C++】set map 的底层封装
  • JavaWeb整体介绍
  • 一些常见分布-正态分布、对数正态分布、伽马分布、卡方分布、t分布、F分布等
  • 科技云报道:押注向量数据库,为时过早?
  • 铭控传感亮相2023国际物联网展,聚焦“多场景物联感知方案”应用
  • 前端demo: 实现对图片进行上传前的压缩功能
  • 计算机网络(文章链接汇总)
  • 黑科技-Android
  • 450. 删除二叉搜索树中的节点
  • python安全工具开发基础
  • 26 docker前后端部署
  • [linux] SFTP文件传输基本命令 --- xshell 直接上传文件
  • Tomcat 多实例
  • 全民拼购模式:电商的新趋势和机遇