多线程调优 - 之ZIP文件解析处理

一、需求背景

接到需求是要对商家提供的数据文件解析为对应我们业务需要的对象,由于商家给的文件是zip文件,大小在10-100M直接,如果用单个线程处理解析势必会影响处理速度,

以下是我们解析时候写的代码。大概思路是这个样子:

1、技术方案一

  1. 解析zip文件:

    1. 由于zip文件中有对应自己要解析的流文件,解读流中指定的文件,获得对应的文件流。
    2. 单个线程测试读取流数据感觉还可以接受,处理时间大概在2000ms之内。
    3. 重点考虑多个线程去消费,需要将处理后的数据放在某一个队列中,让消费者去解析
  2. 生成对象列表:

    1. 处理解析出来的数据,生成我们需要的对象数据列表。
    2. 主要是消费文件解析出来的行数据。将数据处理为对应的对象。
    3. 将数据放入对应的列表中,这样在获取列表的数据进行后续的操作。
  3. 将对象持久化:

    顺序读取列表中的数据,将解析出来的对象做持久化操作。对列表中的数据进行入库。

按照上边的分析,我们可能需要对几个地方可以进行多线程优化。按照这个思路就开干。

(1)处理代码

初期的消费代码是这个样子的。

img

启动测试后发现反射生成实例的时候出现以下情况,主要cpu的处理时间

(2)性能优化排查思路1

设置线程数量为2,CPU使用情况

img

cpu处理快照

img

cpu快照

img

线程的使用情况

img

执行后的处理时间为46164ms

img

将obj=(T)constructor.newInstance(line);对应的代码换成以new Object的方式。

(3)性能优化排查思路2

CPU线程树

img

线程快照

img

线程的使用情况

img

执行后的处理时间46937ms看起来没有什么差别

img

我们看到快照中有个细节。看到在list中添加数据时候的时间耗时挺长。我们看到操作list的数据为target = Lists.newCopyOnWriteArrayList();

该列表之前考虑是在处理数据时候多线程可以安全,有一个add的操作target.add(obj),我们将对应add的那个列表修改成为每个线程维护一个列表,再合并,相当于做了一个缓存。

CPU线程树

img

CPU快照没有抓到:

线程的使用情况:

img

执行后的处理时间4678ms直接影响了一个级别。

img

上边都是设计问题,

不要着急,还没有玩,你多执行几次就会知道上边的那个结果是有偶然性的,我们执行时候会执行到一半就会阻塞到哪里。一直排查不出什么问题。执行一次可以,两次可以,执行次数多了就会有问题。打印堆栈信息显示队列阻塞,但是线程还是不释放。在实际中这种问题最难排查,一个小的细节你可能就会引起大问题。

2、技术方案二

(1)处理代码
  1. 解析zip文件:

    1. 由于zip文件中有对应自己要解析的流文件,解读流中指定的文件,获得对应的文件流。
    2. 单个线程测试读取流数据感觉还可以接受,处理时间大概在2000ms之内。
    3. 重点考虑多个线程去消费,需要将处理后的数据放在某一个队列中,让消费者去解析
  2. 生成对象列表:

    1. 处理解析出来的数据,生成我们需要的对象数据列表。
    2. 主要是消费文件解析出来的行数据。将数据处理为对应的对象。
    3. 将数据放入对应的列表中,这样在获取列表的数据进行后续的操作。
  3. 将队列中的数据接入到对应的多个线程消费处理直接入库。不会在列表对象中存放。

可以看到我们在第二版的解析处理中少了对列表的生成。我们将不会对列表进行收集。直接拿来进行处理。

解析按照列表批量处理。还是单条数据处理。

思路2的代码没有记录。简单就是创建一个线程解析,多个线程消费处理。但是写的时候用的是CountDownLunch这个来控制是否已经都处理完成。但是在控制时候没有考虑到内存的泄漏问题。最后又在利辉老师的提议下整理了现在的版本。

(2)性能优化排查思路3

将zip解析后的数据直接交一个线程池处理。处理不会放入自己维护的队列。直接给到线程池的队列来维护对应的数据。核心的处理就在这里。

img

创建对应的线程池。

img

原来处理数据的任务没有变,创建了新的task作为处理的载体。

img

执行后的结果相当棒。

看看我们监控界面,相当完美啊。

img

对应的生产项目的处理监控CPU使用

img

原文连接

  • https://blog.csdn.net/u013642886/article/details/79125760
  • https://note.youdao.com/ynoteshare1/index.html?id=cbeee975a075fb40e212cd41f698f319
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值