【问题标题】:How to avoid Java OutofMemoryError Heap Space in loop with StringBuilder? [duplicate]如何使用 StringBuilder 避免循环中的 Java OutofMemoryError 堆空间? [复制]
【发布时间】:2017-11-08 00:45:04
【问题描述】:

这是我抛出java.lang.OutOfMemoryError: Java heap space的代码:

StringBuilder sb = new StringBuilder();
    for (int i = 0; i< ranks.size(); i++) {
        Map<String, String> map = ranks.get(i);
        sb.append("SELECT ");
        int iter = 0;
        for (String key : map.keySet()) {
            if (key.equals("ware_md5")) {
                sb.append("'").append(map.get(key)).append(" ' AS ").append(key);
            }
            else {
                sb.append(map.get(key)).append(" AS ").append(key);
            }
            if (iter < map.keySet().size() - 1) {
                sb.append(",");
            }
            iter++;
        }
        if (i < ranks.size() - 1) {
            sb.append(" UNION ALL ");
        }

    }
    return sb.toString();

'ranks' ArrayList 包含大约 30 000 个值

有没有什么办法可以重写这个和平的代码来避免这个错误?

【问题讨论】:

  • 你打算用这么大的字符串做什么?也许您应该直接写入文件? map.keySet() 的大小是多少?
  • 这里我正在尝试生成某种类型的 SQL 请求,map.keySet() 的大小约为 220 条记录
  • 即使您解决了内存问题,也可能会遇到许多问题。数据库可能无法处理的 1 个大查询。大量联合,其性能将对数据库服务器以及返回的行数造成很大影响。我建议少做多做的方法
  • 恐怕 SQL request 的大小在大多数数据库中都会受到相当小的限制,例如 MySQL 中的 1MB(但 Postgres 中为 1GB)。即使您可以发送这么大的查询,执行它也可能会面临一定的困难。您确定要在一次查询中查询 30k 表吗?使用ThreadPoolExecutor 并行运行数十或数百个较小的查询可能会带来更好的整体性能。在接收端可以轻松实现union all的效果。

标签: java


【解决方案1】:

使用更大的堆启动 JVM。以 java -Xmx256M 为例,以 256MB 堆为例。

【讨论】:

    【解决方案2】:
    • 更多内存是最简单的解决方案,已经给出了
    • new StringBuilder(100_000) - 至少更快
    • AS key 不是必需的,但对于第一个联合。
    • 请注意,SortedMap 是您所需要的:键的顺序始终相同。
    • 消费ranks.get(i)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多