在我的应用程序中有一个堆转储,令人惊讶的是char[]
保留的堆大约是700MB,这很奇怪(至少对我而言)。同时String
只有150MB。
在我的应用程序中,我只使用了StringBuilder
(使用默认的StringBuilder
构造函数)并尝试避免在添加数据时使用String
。
我的问题是:我们应该总是选择StringBuilder
吗?如果是,我们如何减少它保留的堆?
答案 0 :(得分:0)
可能你可以使用StringInterner,它接受一个StringBuilder以避免不必要地创建对象。你首先用文本填充一个循环的StringBuilder,如果匹配该文本的String在interner中,则返回该String(或者toString()of StringBuilder是。)好处是你只看到一个新的String(或者至少一个不在数组中)创建对象(并且不超过需要)这可以获得80%到99%的命中率并减少内存加载许多数据字符串时,消耗(和垃圾)显着。
答案 1 :(得分:0)
是的,在构建字符串时总是选择StringBuilder
- 这是连接字符串的最有效但最方便的方法。
听起来有很多StringBuilder
在等待垃圾收集。但是,为了减少堆使用,您可以安全重用您的StringBuilder
即使它们不是线程安全的,通过StringBuilder
每个线程使用一个Threadlocal
:
private static final ThreadLocal<StringBuilder> LOCAL_STRING_BUILDER =
ThreadLocal.withInitial(StringBuilder::new);
使用示例:
public String logMessage() {
StringBuilder sb = LOCAL_STRING_BUILDER.get();
sb.setLength(0); // Only resets the pointer to start. Doesn't affect the backing array
sb.append("foo=").append(myField); //etc
return sb.toString();
}
你最多只有StringBuilder
个和线程一样多,{em> 很多(可能是10's - 100's)。
FYI StringBuilder
;这一行来源:
String str3 = str1 + str2;
被编译为好像是:
String str3 = new StringBuilder().append(str1).append(str2).toString();