内存安全的队列

资料来源:https://juejin.cn/post/7105968458851942414

一般队列要么指定队列长度,要么无界;
指定长度,队列中元素有的大,有的小,按数量来,不能保证需要占用多少内存;
无界队列,随便装,指不定就把内存撑爆了。
介绍2个内存相对比较安全的队列,由系统内存来控制队列中的元素数量,这个思路很有意思。

MemoryLimitedLinkedBlockingQueue

限制内存的队列
每次放入元素时,先检查该元素占用内存的大小(使用Instrumentation 这个类来获取元素大小),并且队列内部用一个字段来存储所有已放入的元素的总大小,每次放入前都先判断是否超过了限定的内存大小,如果超过了就等待,先不放入队列,直到队列中有元素被移除,释放了被移除元素占用的空间再放入队列,以此来防止oom。
缺点:
通过Instrumentation来获取元素大小,只能获取元素本身占用的大小,元素引用的就不能正确获取了。
Instrumentation是个接口,它的实现类InstrumentationImpl构造方法又是private的,不能自己实例化,不会用也挺麻烦的,在这里插入图片描述

MemorySafeLinkedBlockingQueue

内存安全的队列
队列内部定义一个变量叫最大剩余内存,默认值是256M;往队列中放入新元素时,先会检查系统的剩余内存(通过ManagementFactory 里面的 MemoryMXBean来获取),如果系统剩余内存低于设定的最大剩余内存就不再添加,直接丢弃,因此队列始终不会占满内存,以此防止oom。 在这里插入图片描述

代码复制出来后看了下,发现获取剩余内存不是通过MemoryMXBean了,而是通过Runtime.getRuntime().freeMemory();来的,然后通过定时任务每隔50ms刷新一下。

在这里插入图片描述

缺点:
ManagementFactory 的 MemoryMXBean是查看当前堆内存的实际占用,但是没有考虑GC的影响,可能当前内存不够,但是也许内存大部分都是能回收的,回收后就有足够的内存了。我觉得这个问题不大。

这2个队列不是JDK里面的,是提交在dubbo里面,当时呢这2个类又不依赖dubbo,所以把这两个类直接复制出来就能用。

MemoryLimitedLinkedBlockingQueue :
https://github.com/apache/dubbo/pull/9722/files

MemorySafeLinkedBlockingQueue :
https://github.com/apache/dubbo/pull/10021/files

第一个链接里面的代码复制出来后注意 MemoryLimiter这个类里面有bug,在第二个链接里面对这个bug进行了修改。

如果以后有遇到用Map或其他容器做本地缓存的也可以借鉴这个思路,做一个限定内存的容器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值