假设我们的应用程序只有一个线程。我们正在使用StringBuffer
那么有什么问题?
我的意思是如果StringBuffer
可以通过同步处理多个线程,那么使用单线程有什么问题?
为什么要StringBuilder
改用?
假设我们的应用程序只有一个线程。我们正在使用StringBuffer
那么有什么问题?
我的意思是如果StringBuffer
可以通过同步处理多个线程,那么使用单线程有什么问题?
为什么要StringBuilder
改用?
StringBuffers
是线程安全的,这意味着它们具有控制访问的同步方法,因此一次只有一个线程可以访问 StringBuffer 对象的同步代码。因此,StringBuffer 对象通常可以安全地用于多线程环境中,其中多个线程可能试图同时访问同一个 StringBuffer 对象。
StringBuilder's
访问不同步,因此它不是线程安全的。通过不同步,StringBuilder 的性能可以优于 StringBuffer。因此,如果您在单线程环境中工作,使用 StringBuilder 而不是 StringBuffer 可能会提高性能。这也适用于其他情况,例如只有一个线程将访问 StringBuilder 对象的 StringBuilder 局部变量(即方法中的变量)。
所以,更喜欢StringBuilder
因为,
看一下这个 :
StringBuilder 应该快一点(小),因为它不是同步的(线程安全的)。
您可以注意到真正繁重的应用程序中的差异。
通常应优先使用 StringBuilder 类,因为它支持所有相同的操作,但速度更快,因为它不执行同步。
http://download.oracle.com/javase/6/docs/api/java/lang/StringBuffer.html
在多个线程中使用 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 之类的类)要复杂得多。
StringBuffer
在单线程应用程序中没有错。它的工作原理和StringBuilder
.
唯一的区别是所有同步方法所增加的微小开销,这在单线程应用程序中没有任何优势。
我的观点是,引入的主要原因是编译器在编译包含连接的代码时使用(和现在):在这些情况下,永远不需要同步,并且用非同步替换所有这些地方可以提供小的性能改进.StringBuilder
StringBuffer
StringBuilder
String
StringBuilder
StringBuilder
具有更好的性能,因为它的方法不同步。
因此,如果您不需要同时构建 String (无论如何这是一个相当不典型的场景),那么就没有必要“支付”不必要的同步开销。
这将帮助你们,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 ->
Manish,虽然只有一个线程在您的 StringBuffer 实例上运行,但在调用 StringBuffer 实例的任何方法时获取和释放该实例上的监视器锁都会产生一些开销。因此 StringBuilder 是单线程环境中的首选。
同步对象的成本很高。不要将程序视为独立的实体;当您阅读这些概念并将它们应用于您在问题详细信息中提到的小程序时,这不是问题,当我们想要扩展系统时会出现问题。在这种情况下,您的单线程程序可能依赖于其他几个方法/程序/实体,因此同步对象可能会在性能方面导致严重的编程复杂性。因此,如果您确定不需要同步对象,那么您应该使用 StringBuilder,因为它是一种很好的编程习惯。最后,我们想学习编程来制作可扩展的高性能系统,这就是我们应该做的!