2

我是一个 n00b,所以很抱歉,如果我不同意这个,但我使用 arraydeque 作为一些线程处理的队列。每个线程处理队列中的一个项目(每个线程检查队列中是否有数据,如果有,则执行 queue.poll(),如果它很好,则将其发送到解决方案队列中,否则数据将被丢弃或其中一部分被送回队列进行进一步处理。

这是我的问题,我的程序运行的时间越长,它使用的内存就越多,最终我得到内存不足的错误(但在这种情况发生之前它会保持一段时间)。我正在学习 java,所以我不确定我是否正确识别了这一点,但我在我的代码上运行了 yourkit,它说:

Find arrays with big number of 'null' elements.
Problem: Possible memory waste.
Possible solution: Use alternate data structures e.g. maps or rework algorithms.

yourkit 还向我展示了我 93% 的内存卡在此处(在堆转储中)。昨天我问了一个关于 arraydeque.polling() 可能是内存猪的问题,并得到评论说这不是因为我的数据在轮询后变成了“空”。

所以我的两个问题(如我的标题)是有一个不断增长的空对象的问题(我不确定它们是否得到了 GC,但由于堆转储中有几百万,我怀疑可能不是)?如果是这样,是否有 ArrayDeque 的替代品,也许是 GC 的项目不再需要时的东西(我的程序不断处理并在队列中添加项目,但即使要处理的项目数量减少了内存消耗也不会消失下来,当程序完成时突然变为零,如果队列逐渐建立,我希望它会逐渐变小)?

另一个稍微相关的问题,我正在处理由线程处理的队列中的数十亿个项目,但内存导致它失败。尝试改进我的内部程序队列有什么意义,还是使用真正的队列程序(如(rabbitmq 或 activemq)更有意义?(我真的是编程新手,所以不确定我什么时候达到了一个限制)工具以及如何改进它或弄清楚下一步要使用什么)

4

2 回答 2

4

看起来这个ArrayDeque实现永远不会缩小它的内部数组,所以它只会永远增长。当从双端队列轮询一个对象时,其对应的数组元素设置为null,并且该对象最终将被垃圾回收(如果对它的所有其他引用也消失了)。但是内部数组ArrayDeque只是不断增长。

Deque接口也由LinkedListand实现ConcurrentLinkedDeque,因此您最好使用其中之一。

于 2012-04-13T21:50:21.710 回答
4

ArrayDeque借助两个“指针” - 头和尾,将项目存储在平面数组中。如果队列中的元素总数超过此数组的当前大小,则其大小加倍。

当您从队列中轮询一个项目时,该数组中的槽被清除(设置为null),但该数组永远不会真正缩小!这意味着如果您首先向队列提供百万个项目,然后轮询所有这些项目,那么ArrayDeque仍然会维护一个包含至少 100 万个条目的数组,所有条目都设置为null. 这解释了查找具有大量“空”元素的数组消息。

似乎您的应用程序在某个时间点为队列提供了大量元素。尝试(定期?)调用以下代码:

queue = new ArrayDeque<String>(queue);

这将复制旧的queue、垃圾收集不必要的大内部数组的内容。

请注意,没有空对象之类的东西- 如果您从队列中删除了一个项目并且您的代码不再引用该项目 - 它将被垃圾收集。

于 2012-04-13T21:57:59.500 回答