再不解决延迟不当,当心你的内存被打爆

摘要:这是在具体代码中发现的不当延迟的问题,极端状况下可能把内存打爆。

本文分享自华为云社区《线程中不当使用延迟问题》,原文做者:技术火炬手 。java

背景

这是在具体代码中发现的不当延迟的问题,极端状况下可能把内存打爆。算法

代码DevLicenseServiceRoaDelegateImpl.javasegmentfault

定义:
image.pngapi

使用:
image.png数据结构

signalRefreshHelp 定义
image.png并发

这段代码最大问题是使用延迟算法不当,在极端状况下会致使内存暴涨,严重影响服务程序的性能。高并发

不要使用sleep来实现延迟

使用sleep实现延迟看起来很是直观,可是这个在高并发、多请求、长期运行的服务程序里必须特别当心。这是由于衡量服务程序性能的一个很是重要的指标是QPS, 就是服务程序的处理能力,通常状况下越大越好;服务程序的总并发能力等于每一个线程的qps;单个线程的QPS = 1000毫秒 / (处理一个请求的毫秒);因此上面那个线程的QPS <= 1000 / 10000 = 0.1 (由于线程sleep了10000毫秒)。性能

这里的处理逻辑是错误的!也有很严重的性能隐患,不过幸亏调用这个api 请求很少,才没有致使严重问题。测试

开发者的意图是在建立一个任务后,延迟10s执行该任务,处理时序图以下
image.pngspa

假如时间点t1 & t2 挨得很接近的话,线程在执行job1 & job2 也是很接近。

但实际的状况变成:
image.png

就算建立job1 & job2的时间很接近,但job2执行的时间会比预期多了10s;连续提交的任务越多,越容易堆积,这些堆积的任务存放在 blocking queue,一直处处理完毕才删除;若是这类请求不少的话,很容易引发内存爆掉。

解决方案

选择合适的数据结构,默认线程池关联的队列是LinkedBlockingQueue , 没有延迟控制,可使用DelayQueue
image.png

DelayQueue内部使用了PriorityQueue 按时间排序;须要本身使用Delayed 接口封装请求数据

下面是例子
image.png

测试代码,同时加入 3个须要延迟10s的任务
image.png

测试结果:
image.png

符合预期

点击关注,第一时间了解华为云新鲜技术~

相关文章
相关标签/搜索