不灭的焱

革命尚未成功,同志仍须努力下载JDK17

作者:Albert.Wen  添加时间:2023-04-02 16:47:32  修改时间:2024-04-30 15:37:13  分类:安全测试/性能测试/JMeter  编辑

有一个线程的问题,就是假如 我有一个文件,然后这个文件有很多条数据,假如有两个字段,一个学号一个钱,(我的需求是,读取文件,把数据插入到表里,先拿文件的学号去查表有这个数据,就把钱进行相加,没有就新增一条数据)现在遇到问题是:我开多线程跑,现在出现了,这个表里有两条数据的概念(不应该是两条,因为读文件有就把钱相加,没有就新增),我感觉是,多个线程拿到了两条一样的学号同时去库里查,都没有查到,把这两条同时新增到了表里。

没看懂?简说下

if (用户不存在) {
    xxxxx
    存储用户到数据库
} else {
   更新数据,将钱数进行相加
}

意思是在一条线成操作还没有执行完毕,第二条拥有相同数据的线程已经进入并通过了if的检验,导致数据库存储了两条相同的数据。所以就会导致数据不对,钱并没有加上且数据库出现了多条数据

然后我就百度了一下感觉有一个大佬做出了这个比喻,我觉得很恰当祥和里分享下:

插入Java多线程不安全的场景比喻:苹果饮食竞赛,比如三个人同时吃10个苹果,就会有一个数字问题:当同时执行多个线程的时候,可能会出现线程不安全的问题,当三个人同时获得一个苹果时,他们同时执行了这个操作,就会产生多条数据操作。

解决方案:

然后我就查了许多资料,然后也听朋友说了许多

  1. 解决的办法,当然加锁是我万不得已的选择才会去选择,因为以我现在的水平,我觉得我对线程的了解仅仅是九牛一毛,根本操控不了
  2. 还有一个办法就是说首先把所有的文件数据全部导入一张临时表,然后对临时表进行分组 统一进行金钱相加,(说实话这个方法可行,但是时间问题,200多万的数据确实会很慢,所以我也只是考虑并没有使用)
  3. 最后我想到一个方法就是对查询的学号做约束(也就是做唯一索引,让程序进行插入的时候进行报错,也就是说在sql中如果学号重复,再次进入插入的时候就会报索引唯一 key 什么玩意),然后我在写的代码中进行捕获,一开始怎么捕获还是会抛出错误,后来发现,那个sql主键重复并不是异常,而是error,然后我就记得error也能进行捕获,后来我又找到error的捕获:

error和exception都是可以捕获的,他们两个都是Throwable的子类(这里是重点) 

最后我将代码改为:

if (用户不存在) {
	try {
    	xxxxx
    	存储用户到数据库
	} catch(Throwable e){
  		更新数据,将钱数进行相加
	}
} else {
   更新数据,将钱数进行相加
}

问题解决 !!!

 

 

摘自:https://blog.csdn.net/wsyzcj/article/details/109483667