案例15-ArrayList线程不安全,共用全局变量导致数据错乱问题,占用内存情况
创始人
2025-05-29 22:07:25
0

目录

    • 背景
        • **1、使用了线程不安全的ArrayList作为公共变量
        • **2、每次给Arraylist重新赋值的时候都创建了一个新的对象,堆积了大量要回收的旧对象,导致CPU飙升****
    • 思路&方案
          • 1、在方法之前加 **synchronized** 关键字。
          • 2、使用**ThreadLocal**变量。
    • 总结

背景

存入redis的值,可能会出现错误的情况。如果出现错误,接口将会报错。
多个方法一起修改一个公共变量的值,造成数据混乱,导致存入redis中的key值错误
还有每次登陆都会重现创建一个对象,放到公共变量中,遇到并发,对象会被大量地创建,
上一个对象会失去引用,等待垃圾回收器进行回收,导致CPU飙升。

在这里插入图片描述
上边公共变量的字符串拼接出现问题,导致下边这张图中的域名中的字符串出现问题。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
由上图可知:

**1、使用了线程不安全的ArrayList作为公共变量

2、每次给Arraylist重新赋值的时候都创建了一个新的对象,堆积了大量要回收的旧对象,导致CPU飙升**

(GC会消耗大量CPU和内存来实现垃圾回收)

思路&方案

复现问题:

测试类:

public class ThreadTest {//新建一个list作为成员变量List testList ;public void updateTestList(){testList = new ArrayList<>();testList.add("a01+");testList.add("a02+");testList.add("a03+");testList.add("a04+");//打印一下看看有什么System.out.println("updateTestList"+testList);}public void updateTestList2(){testList = new ArrayList<>();testList.add("b01+");testList.add("b02+");testList.add("b03+");testList.add("b04+");//看一下list里有什么System.out.println("updateTestList2"+testList);}
}

客户端:

public class Main {public static void main(String[] args) {ThreadTest threadTest = new ThreadTest();//开一个多线程测试一下for (int i = 0; i < 100; i++) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {threadTest.updateTestList();threadTest.updateTestList2();}});thread.start();}}
}

正常结果只会出现下面两种情况
updateTestList[a01+, a02+, a03+, a04+]
updateTestList2[b01+, b02+, b03+, b04+]

实际上:
在这里插入图片描述

注重变量的作用域和生命周期,还要考虑并发量高的时候考虑线程安全,并发的时候还要将对象进行置空。

第一个问题解决方案:

1、在方法之前加 synchronized 关键字。

在这里插入图片描述

2、使用ThreadLocal变量。
public class ThreadTest2 {ThreadLocal> testList = ThreadLocal.withInitial(()->new ArrayList<>());public  void updateTestList(){testList.get().removeAll(testList.get());testList.get().add("a01+");testList.get().add("a02+");testList.get().add("a03+");testList.get().add("a04+");//打印一下看看有什么System.out.println("updateTestList"+testList.get());}public  void updateTestList2(){testList.get().removeAll(testList.get());testList.get().add("b01+");testList.get().add("b02+");testList.get().add("b03+");testList.get().add("b04+");//看一下list里有什么System.out.println("updateTestList2"+testList.get());}
}

结果:
在这里插入图片描述

第二个问题(对象重复创建导致CPU和内存飙升)解决方案:
1、使用List的RemoveAll方法将对象进行清除。
现状:在这里插入图片描述
在这里插入图片描述

这样就不会持续开辟内存空间。

总结

考虑成本,凡事都要考虑成本。
我们要有无限思维,当只有一个对象的时候我们写的代码不会出现上述问题,但是对象一多就会出现数据错乱的问题,内存飙升的问题,我们的系统不会只有一个用户,所以无限思维是我们必须要考虑的一件事情,考虑并发,考虑将来。而不是只顾眼前。

相关内容

热门资讯

钦州最新学区划分,最新或202... 钦州市区最新或2023(历届)初中学区划分方案根据《中华人民共和国义务教育法》《广西壮族自治区实施〈...
温州最新学区划分,最新或202... 温州公办小学招生范围按照义务教育免试就近入学原则,市区公办小学实行依街道划片招生。本文为您介绍温州小...
绍兴最新学区划分,最新或202... 绍兴公办小学招生范围按照义务教育免试就近入学原则,市区公办小学实行依街道划片招生。本文为您介绍绍兴小...
金华最新学区划分,最新或202... 金华公办小学招生范围按照义务教育免试就近入学原则,市区公办小学实行依街道划片招生。本文为您介绍金华小...
湖州最新学区划分,最新或202... 学校名称划片区域湖师附小教育集团(幸福里校区、余家漾校区、西山漾校区)潜庄公寓、白漾港小区、米兰花园...
PHP操作文件和目录 PHP操作文件和目录一、目录处理1.1 目录信息查询1.2 目录操作二、文件处理2.1 查询文件信息...
小白开发微信小程序20--we... 1、什么是SwaggerSwagger 项目已于 2015 年捐赠给 OpenAPI 计划ÿ...
台州最新学区划分,最新或202... 台州公办小学招生范围按照义务教育免试就近入学原则,市区公办小学实行依街道划片招生。本文为您介绍台州小...
衢州最新学区划分,最新或202... 柯城区最新或2023(历届)学区划分衢江区最新或2023(历届)学区划分
舟山最新学区划分,最新或202... 临城新区】1、南海实验小学片区:新城沈白线以南、千岛路以西区域,以及长峙社区居民子女。2、舟山第二小...
④电子产品拆解分析-太阳能自动... ④电子产品拆解分析-太阳能自动感应灯一、功能介绍二、电路分析以及器件作用1、太阳能控制电路分析2、优...
丽水最新学区划分,最新或202... 根据“就近入学,统筹安排”为原则,公办小学学区划分也已出炉。  市实验学校:丽阳门居委、高井弄居委。...
海南最新学区划分,最新或202... 1.市直属学校招生范围划分小 学招 生 范 围海口市滨海第九小学滨海大道北侧(至海边),港进路和港集...
从ChatGPT到AGI还有多... 1.引子 21年开始在公司负责一个全链路语音的项目,支持公司的Iot设备,...
海口最新学区划分,最新或202... 海口公办小学招生范围按照义务教育免试就近入学原则,市区公办小学实行依街道划片招生。本文为您介绍海口小...
青海最新学区划分,最新或202... 为方便家长和学生们了解自己孩子所就读的小学或是自己孩子的户口究竟在不在想要入读的中学的学区范围内,小...
西宁最新学区划分,最新或202... 西宁公办小学招生范围按照义务教育免试就近入学原则,市区公办小学实行依街道划片招生。本文为您介绍西宁小...
三亚最新学区划分,最新或202... 三亚公办小学招生范围按照义务教育免试就近入学原则,市区公办小学实行依街道划片招生。本文为您介绍三亚小...
贵州最新学区划分,最新或202... 为方便家长和学生们了解自己孩子所就读的小学或是自己孩子的户口究竟在不在想要入读的中学的学区范围内,小...
21- 神经网络模型_超参数搜... 知识要点 fetch_california_housing:加利福尼亚的房价数据&#...