循环StringBuilder内存泄漏

时间:2013-12-04 20:34:58

标签: java memory-leaks stringbuilder

对于我的数据结构类中的项目,我们必须使用广度优先和深度优先遍历来遍历图形。在这种情况下,深度优先遍历通常在1到100,000个节点之间。

每个节点的内容都是一个字符串。遍历图表并找到解决方案并不是一个大问题。但是,一旦遍历完成,就必须显示它。

为此,我返回每个节点的父节点,并将节点的字符串添加到Stack。在这一点上,代码运行正常(据我所知)。尝试显示这些字符串时会出现大幅减速。

如果堆叠了数万个字符串,我该如何显示它们?直接调用System.out.println()需要太长时间。然而迭代地使用StringBuilder会以某种方式消耗内存。我试图以相当随意的间隔(以相当粗暴的方式)清除StringBuilder,这似乎有点帮助。同样引入一个小睡眠似乎也有帮助。无论哪种方式,当函数完成打印时,Java已经耗尽内存,或者速度极慢而且没有响应。

有没有什么方法可以重构这段代码,以相对及时的方式输出所有字符串(~10秒不应该要求太多),而不会崩溃VM?

if(DFSResult.hash().equals(myPuzzle.answerHash()))
{
  System.out.println("Success");
  int depth = 0;
  while(DFSResult.parent != null)
  {
    depth++;
    if(in.equals("y")) dfs.push(DFSResult.hash());
    DFSResult = DFSResult.parent;
  }
  System.out.println("found at a depth of "+depth+"\n\n");
  StringBuilder s = new StringBuilder();
  int x = 0;
  boolean isSure = false;
  if(in.equals("y"))
  {
    System.out.println("Are you really sure you want to print out a lineage this long? (y/n)");
    try{
      if(input.readLine().toLowerCase().equals("y"))isSure = true;
    }catch (Exception e) {
    }//
  }
  s = new StringBuilder();
  while(!dfs.empty() && isSure)
  {
    //System.out.println(dfs.pop());
    s.append(dfs.pop()).append("\n");
    x++;
    if(x % 500 == 0)
    {//Flush the stringbuilder
      try{Thread.sleep(50);}catch(Exception e){e.printStackTrace();}
      System.out.println(s.toString());
      s.delete(0,s.length());//supposed 25% efficiency increase over saying s = new StringBuilder()
    }
  }
  System.out.println(s.toString());

1 个答案:

答案 0 :(得分:1)

您的示例中不需要使用StringBuilder。 而只是做:

System.out.println(dfs.pop());
循环中的

。也不需要睡觉。循环中只有一行。

System.out.println()效率没有问题。请考虑以下代码:

public class TestMain {
  public static void main(String[] args) {
    long timeBefore = System.currentTimeMillis();
    for (int i = 0; i < 50000; i++) {
        System.out.println("Value = " + i);
    }
    long timeAfter = System.currentTimeMillis();
    System.out.println("Time elapsed (ms): " + (timeAfter - timeBefore));
  }
}

这是我机器上的最后一行输出:

. . .
Value = 49994
Value = 49995
Value = 49996
Value = 49997
Value = 49998
Value = 49999
Time elapsed (ms): 538

你可以看到它超级快。问题不在println()方法中。

下面的堆栈使用示例:

public static void main(String[] args) {
    long timeBefore1 = System.currentTimeMillis();
    Stack<String> s = new Stack<String>();
    for (int i = 0; i < 50000; i++) {
        s.push("Value = " + i);
    }
    long timeAfter1 = System.currentTimeMillis();
    long timeBefore2 = System.currentTimeMillis();
    while (!s.isEmpty()) {
        System.out.println(s.pop());
    }
    long timeAfter2 = System.currentTimeMillis();
    System.out.println("Time spent on building stack (ms): " + (timeAfter1 - timeBefore1));
    System.out.println("Time spent on reading stack (ms): " + (timeAfter2 - timeBefore2));
}

输出:

. . .
Value = 2
Value = 1
Value = 0
Time spent on building stack (ms): 31
Time spent on reading stack (ms): 551