kafka消息堆积且CPU过高代码优化

直接部署已有的代码程序到线上服务器,发现CPU立马升高500%左右,立马停掉服务并看源代码排查问题,翻看代码,发现通过多线程消费
kafka消息,根据对多线程的了解,立马从以下方面排查问题:
 1.多线程必须保证单例模式,才能保证多线程安全问题
 2.共享资源的竞争问题,有共享变量必须加锁(synchronized)同步
 3.代码性能优化(jvm和数据库两个方面进行优化)

逐个分析排查:
 对于第一个线程安全问题,开启多个线程来分别获取单例,然后打印它们所获取到的单例的hashCode值。
 若它们获取的单例是相同的(该单例模式的实现是线程安全的),那么它们的hashCode值一定完全一致;若它们的hashCode值不完全一致,
 那么获取的单例必定不是同一个,即该单例模式的实现不是线程安全的,是多例的。通过本地测试打印发现hashCode值不一样,立马修改代码,
 我使用内部类实现线程安全的懒汉式单例,这种方式是一种效率比较高的做法(注意:使用双重检测同步延迟加载去创建单例的做法是一个非常优秀的做法,
 其不但保证了单例,而且切实提高了程序运行效率)。

保证单例模式代码截图:

对于第二个资源共享的问题,有成员变量的可以通过加volatile关键字,变量的可见性。

对于第三个代码性能问题解决思路:

数据库层面:单条数据插入耗资源,每次插入数据都会预编译一次,可以改成批量插入。

jvm层面:在知道集合大小的情况下可以给集合一个初始化大小,避免多次扩容好资源。内存模型

初次优化后部署到线上,发现CPU在100%左右,CPU有所下降,但是还是偏高,继续二次优化。

第二次优化,我直接本地直接注释掉判断经纬度是否边界区域那部分代码(判断代码见下图),for循环是每次都要Double.parseDouble()方法转换耗时,有个时间复杂度,找到问题点,
代码性能不足,经过请教后,将for循环中的代码double转换在外面直接处理好,for循环直接get取值就是double类型。

优化前代码截图:

优化后代码截图:

二次线上部署,发现CPU在30%左右,达到目标期望。

总结:用到了kafka技术和多线程,由于对kafka不是很了解,仅从多线程及jvm和数据库层面优化。由于线程在CPU上运行,而CPU是抢占式的(时间片),因此内存模型中有个程序计数器,专门记住行号,
当运行在此线程中的CPU资源被其他线程抢走后,我们的程序计数器就会记住这个行号,等此线程抢到CPU资源后继续从这个行号开始运行。