假设我们的应用程序只有一个线程。我们正在使用StringBuffer
那么问题是什么?
我的意思是如果StringBuffer
可以通过同步处理多个线程,那么单线程有什么问题?
为什么要使用StringBuilder
?
答案 0 :(得分:27)
StringBuffers
是线程安全的,这意味着它们具有控制访问的同步方法,因此一次只有一个线程可以访问StringBuffer对象的同步代码。因此,StringBuffer对象通常可以安全地在多线程环境中使用,其中多个线程可能试图同时访问同一个StringBuffer对象。
StringBuilder's
访问未同步,因此它不是线程安全的。通过不同步,StringBuilder的性能可以比StringBuffer更好。因此,如果您在单线程环境中工作,则使用StringBuilder而不是StringBuffer可能会提高性能。对于其他情况也是如此,例如StringBuilder局部变量(即方法中的变量),其中只有一个线程将访问StringBuilder对象。
所以,更喜欢StringBuilder
因为,
检查出来:
答案 1 :(得分:7)
StringBuilder应该更快(微小),因为它不同步(线程安全)。
您可以注意到真正繁重的应用程序存在差异。
StringBuilder类通常应优先于此使用,因为它支持所有相同的操作,但速度更快,因为它不执行同步。
http://download.oracle.com/javase/6/docs/api/java/lang/StringBuffer.html
答案 2 :(得分:5)
在多个线程中使用StringBuffer是无用的,实际上几乎从未发生过。
考虑以下
Thread1: sb.append(key1).append("=").append(value1);
Thread2: sb.append(key2).append("=").append(value2);
每个追加都是同步的,但是线程可以随时弯腰,这样你就可以拥有以下任何组合和更多
key1=value1key2=value2
key1key2==value2value1
key2key1=value1=value2
key2=key1=value2value1
这可以通过一次同步整行来避免,但是这使得使用StringBuffer而不是StringBuilder失败了。
即使你有一个正确同步的视图,它也比创建整行的线程本地副本更复杂,例如StringBuilder和日志行一次到类似Writer的类。
答案 3 :(得分:3)
StringBuffer
在单线程应用程序中不是错误。它的工作方式与StringBuilder
一样。
唯一的区别是拥有所有同步方法所带来的微小开销,这在单线程应用程序中没有任何优势。
我的观点是引入了 main 原因StringBuilder
是编译器在编译包含{的代码时使用StringBuffer
(现在是StringBuilder
) {1}}连接:在这些情况下,同步永远不会,并且使用未同步的String
替换所有这些地方可以提供较小的性能提升。
答案 4 :(得分:2)
StringBuilder
具有更好的性能,因为它的方法不同步。
因此,如果你不需要同时构建一个String(这是一个相当不典型的场景),那么就没有必要为不必要的同步开销“付费”。
答案 5 :(得分:0)
这会帮助你们, Be Straight Builder比Buffer慢,
public class ConcatPerf {
private static final int ITERATIONS = 100000;
private static final int BUFFSIZE = 16;
private void concatStrAdd() {
System.out.print("concatStrAdd -> ");
long startTime = System.currentTimeMillis();
String concat = new String("");
for (int i = 0; i < ITERATIONS; i++) {
concat += i % 10;
}
//System.out.println("Content: " + concat);
long endTime = System.currentTimeMillis();
System.out.print("length: " + concat.length());
System.out.println(" time: " + (endTime - startTime));
}
private void concatStrBuff() {
System.out.print("concatStrBuff -> ");
long startTime = System.currentTimeMillis();
StringBuffer concat = new StringBuffer(BUFFSIZE);
for (int i = 0; i < ITERATIONS; i++) {
concat.append(i % 10);
}
long endTime = System.currentTimeMillis();
//System.out.println("Content: " + concat);
System.out.print("length: " + concat.length());
System.out.println(" time: " + (endTime - startTime));
}
private void concatStrBuild() {
System.out.print("concatStrBuild -> ");
long startTime = System.currentTimeMillis();
StringBuilder concat = new StringBuilder(BUFFSIZE);
for (int i = 0; i < ITERATIONS; i++) {
concat.append(i % 10);
}
long endTime = System.currentTimeMillis();
// System.out.println("Content: " + concat);
System.out.print("length: " + concat.length());
System.out.println(" time: " + (endTime - startTime));
}
public static void main(String[] args) {
ConcatPerf st = new ConcatPerf();
System.out.println("Iterations: " + ITERATIONS);
System.out.println("Buffer : " + BUFFSIZE);
st.concatStrBuff();
st.concatStrBuild();
st.concatStrAdd();
}
}
Output
run:
Iterations: 100000
Buffer : 16
concatStrBuff -> length: 100000 time: 11
concatStrBuild -> length: 100000 time: 4
concatStrAdd ->
答案 6 :(得分:0)
Manish,虽然只有一个线程在你的StringBuffer实例上运行,但是只要调用任何方法,就会在StringBuffer实例上获取和释放监视器锁定时产生一些开销。因此,StringBuilder是单线程环境中的首选。
答案 7 :(得分:0)
同步对象的成本很高。不要将程序视为独立实体;当您阅读概念并将其应用于您在问题详细信息中提到的小程序时,这不是问题,当我们想要扩展系统时会出现问题。在这种情况下,您的单线程程序可能依赖于其他几个方法/程序/实体,因此同步对象可能会在性能方面造成严重的编程复杂性。因此,如果您确定不需要同步对象,那么您应该使用StringBuilder,因为它是一个很好的编程习惯。最后,我们想学习编程以制作可扩展的高性能系统,这就是我们应该做的!