【发布时间】:2014-01-22 13:59:30
【问题描述】:
问题在于,由于垃圾收集时间的原因,我在性能上进行了权衡。这个问题可以概括为:
public void loop(BlockingQueue<Runnable> queue)
{
int j = queue.size();
for(int i =0; i<j;i++)//line2
{
Runnable runnable = queue.take();
runnable.run();//line4
if(Math.random() > 0.9) System.gc();//line5
}
//line7 //will 'runnable = null;' answer the question, logically it looks right
}
现在通常作为参数传递的队列通常包含超过 40,000 个元素。 而且因为我在循环中遍历队列,即使已经“运行”的对象超出范围,它们仍然不能用于垃圾收集,因为它们在invisible state 中。因此,如果我没有第 5 行,那么当方法退出堆栈时,垃圾收集器会突然产生巨大的负载。想象一下,如果同时有多个线程访问该方法。
我的问题:
- 需要第 5 行吗?还有其他替代品吗?
- 如果我必须有第 5 行,我发现与没有它相比,它的性能非常非常糟糕。
最终必须进行垃圾收集吗?我不知道什么时候应该发生。
PS:我的电脑上禁用了 Javascript,因此无法评论答案。我将在此处为 cmets 编辑帖子:
@amit:我改了代码,我想你已经明白问题的本质了。代码只是一个示例。
@Tobi:谢谢,但是如何设置更大的堆大小来解决问题。那只是延迟gc的时间。 所以你认为它会在没有手动 gc 的情况下表现最好? 进一步从http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html 开始,它说只有当方法从堆栈中取出时,只有在这种情况下,它才能用于垃圾收集。我尝试使用 finalize() (通过打印,不是正确的方式,但应该至少为 100000 个对象工作一次),绝对没有 gc。
@Paolo:谢谢。我试图实现的是一个流水线模型,其中每个线程都有一个消息队列,基本上是一个框架,任何线程都可以向另一个线程发布一个可运行的(如果它与线程有一些工作),另一个线程将执行他们在一段时间后(空闲时) Ans当我的意思是,当方法从堆栈中出来时重载,我的意思是垃圾收集最终会发生,如果它稍后发生,那么清除40,000个元素将需要很多时间
@ Joachim Sauer : System.gc 可以收集不可见的对象,只是垃圾收集器不会自动收集它们。但是当被强制执行时,它会按照:http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html
【问题讨论】:
-
我改变了:line3:run->runnable, wueue->queue, 如果我错了就回滚,你实际上是指班级成员,但我认为不是
-
另外:我怀疑你想从
i=0迭代到queue.size(),注意queue.size()在你使用take()时会发生变化,所以如果你有2个元素在队列中,你会'迭代' 仅超过第一个,因为在您take()大小更改为 1 和i<1==false之后。可能你正在寻找(queue.isEmpty() == false) -
你说你概括了这个问题:你能用这个概括的代码重现这个问题吗?如果不是,那么您很可能过于概括,可能需要向我们展示真实代码。
-
另外:如果您的问题实际上来自不可见的对象(这不太可能,因为您一次只有相对较少的对象),那么将您的代码打包成更小的方法可能 帮助。另外:当
System.gc()有帮助时,那么您的问题几乎可以肯定不是由不可见的物体引起的(因为System.gc()也无法收集它们!)。 -
是什么让你认为
System.gc()可以收集隐形物体?链接到的文档从不声称这样的内容。事实上,关于隐形物品可收集性的唯一一句话是以“因为无法收集隐形物品,[...]”开头。
标签: java object garbage-collection