StringBuilder和StringBuffer的区别
StringBuffer
和StringBuilder
的主要区别是什么? 在决定其中的任何一个时,是否有任何性能问题?
StringBuffer
是同步的, StringBuilder
不是。
说明:如果一个对象是不可变的,那么它是自动线程安全的。 StringBuffer
是可变的。 可以有多个线程读取/写入可变的StringBuffer
对象。 因此,他们必须同步。 StringBuilder
是不可变的对象,因此不需要同步。 StringBuilder
因为它不需要同步比StringBuffer
快。 http://www.javapractices.com/topic/TopicAction.do?Id=49
StringBuilder
比StringBuffer
快,因为它没有synchronized
。
这是一个简单的基准testing:
public class Main { public static void main(String[] args) { int N = 77777777; long t; { StringBuffer sb = new StringBuffer(); t = System.currentTimeMillis(); for (int i = N; i --> 0 ;) { sb.append(""); } System.out.println(System.currentTimeMillis() - t); } { StringBuilder sb = new StringBuilder(); t = System.currentTimeMillis(); for (int i = N; i --> 0 ;) { sb.append(""); } System.out.println(System.currentTimeMillis() - t); } } }
testing运行给了StringBuffer
2241 ms
的数字和StringBuffer
753 ms
数字。
基本上,StringBuffer方法是同步的,而StringBuilder不是。
这些操作“几乎”是一样的,但是在单个线程中使用同步方法是矫枉过正的。
这几乎是关于它。
从StringBuilder API引用:
这个类[StringBuilder]提供了一个与StringBuffer兼容的API, 但是不保证同步 。 这个类被devise为在单个线程正在使用string缓冲区的地方(如通常情况下)用作StringBuffer的embedded式replace。 在可能的情况下,build议将此类优先用于StringBuffer,因为在大多数实现中它将更快。
所以它取而代之。
Vector和ArrayList也是如此。
但需要通过一个例子来获得明显的区别?
StringBuffer或StringBuilder
只要使用StringBuilder
除非你真的试图在线程之间共享一个缓冲区。 StringBuilder
是原始同步的StringBuffer
类的非同步(开销更小=效率更高)的弟弟。
StringBuffer
先来。 Sun在所有情况下都关心正确性,所以为了防万一,他们把它同步到线程安全。
StringBuilder
来了。 StringBuffer
大部分用途是单线程的,并且不必要地支付同步的代价。
由于StringBuilder
是没有同步的StringBuffer
replace ,所以任何示例都不会有区别。
如果你试图在线程之间共享,你可以使用StringBuffer
,但是考虑是否需要更高级别的同步,例如,可能不是使用StringBuffer,而是同步使用StringBuilder的方法。
首先让我们看看相似之处 :StringBuilder和StringBuffer都是可变的。 这意味着你可以在同一个位置改变它们的内容。
差异 :StringBuffer也是可变的和同步的。 作为StringBuilder是可变的,但默认情况下不同步。
同步(同步)的含义 :当某个事物同步时,多个线程可以访问,并修改它,而不会出现任何问题或副作用。 StringBuffer是同步的,所以你可以使用它与多个线程没有任何问题。
哪一个使用时? StringBuilder:当你需要一个可以修改的string时,只有一个线程正在访问和修改它。 StringBuffer:当你需要一个可以修改的string时,多个线程正在访问和修改它。
注意 :不要不必要地使用StringBuffer,也就是说,如果只有一个线程正在修改和访问它,就不要使用它,因为它有很多locking和解锁代码用于同步,这将不必要地占用CPU时间。 除非需要,否则不要使用锁。
在单线程中,由于JVM优化, StringBuffer并不比StringBuilder慢很多 。 而在multithreading中,你不能安全地使用一个StringBuilder。
这是我的testing:
public static void main(String[] args) { String withString =""; long t0 = System.currentTimeMillis(); for (int i = 0 ; i < 100000; i++){ withString+="some string"; } System.out.println("strings:" + (System.currentTimeMillis() - t0)); t0 = System.currentTimeMillis(); StringBuffer buf = new StringBuffer(); for (int i = 0 ; i < 100000; i++){ buf.append("some string"); } System.out.println("Buffers : "+(System.currentTimeMillis() - t0)); t0 = System.currentTimeMillis(); StringBuilder building = new StringBuilder(); for (int i = 0 ; i < 100000; i++){ building.append("some string"); } System.out.println("Builder : "+(System.currentTimeMillis() - t0)); }
结果:
string:319740
缓冲区: 23
build设者:7!
所以build设者比缓冲区快,比string连接快得多。 现在让我们使用一个Executor来处理多个线程:
public class StringsPerf { public static void main(String[] args) { ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10); //With Buffer StringBuffer buffer = new StringBuffer(); for (int i = 0 ; i < 10; i++){ executorService.execute(new AppendableRunnable(buffer)); } shutdownAndAwaitTermination(executorService); System.out.println(" Thread Buffer : "+ AppendableRunnable.time); //With Builder AppendableRunnable.time = 0; executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10); StringBuilder builder = new StringBuilder(); for (int i = 0 ; i < 10; i++){ executorService.execute(new AppendableRunnable(builder)); } shutdownAndAwaitTermination(executorService); System.out.println(" Thread Builder: "+ AppendableRunnable.time); } static void shutdownAndAwaitTermination(ExecutorService pool) { pool.shutdown(); // code reduced from Official Javadoc for Executors try { if (!pool.awaitTermination(60, TimeUnit.SECONDS)) { pool.shutdownNow(); if (!pool.awaitTermination(60, TimeUnit.SECONDS)) System.err.println("Pool did not terminate"); } } catch (Exception e) {} } } class AppendableRunnable<T extends Appendable> implements Runnable { static long time = 0; T appendable; public AppendableRunnable(T appendable){ this.appendable = appendable; } @Override public void run(){ long t0 = System.currentTimeMillis(); for (int j = 0 ; j < 10000 ; j++){ try { appendable.append("some string"); } catch (IOException e) {} } time+=(System.currentTimeMillis() - t0); } }
现在StringBuffers需要157毫秒 100000附加。 这不是同一个testing,但是与之前的37 ms相比,你可以放心地认为StringBuffers追加在multithreading的使用中会比较慢 。 原因是当JIT /热点/编译器/某些东西检测到不需要检查锁时,会进行优化。
但是对于StringBuilder,你有java.lang.ArrayIndexOutOfBoundsException ,因为一个并发线程试图添加一些不应该的东西。
结论是你不必追逐StringBuffers。 在有线程的地方,在试图获得几纳秒之前,想想他们在做什么。
StringBuilder是在Java 1.5中引入的,因此它不适用于早期的JVM。
从Javadocs :
StringBuilder类提供了与StringBuffer兼容的API,但不保证同步。 这个类被devise为在单个线程正在使用string缓冲区的地方(如通常情况下)用作StringBuffer的embedded式replace。 在可能的情况下,build议将此类优先用于StringBuffer,因为在大多数实现中它将更快。
很好的问题
以下是我注意到的差异:
StringBuffer: –
StringBuffer is synchronized StringBuffer is thread-safe StringBuffer is slow (try to write a sample program and execute it, it will take more time than StringBuilder)
StringBuilder的: –
StringBuilder is not synchronized StringBuilder is not thread-safe StringBuilder performance is better than StringBuffer.
共同的事情: –
两者具有相同的签名相同的方法。 两者都是可变的。
StringBuilder不是线程安全的。 string缓冲区是。 更多信息在这里 。
编辑:至于性能, 热点踢后,StringBuilder是赢家。 但是,对于小的迭代,性能差异可以忽略不计。
StringBuilder
和StringBuffer
几乎是一样的。 不同的是, StringBuffer
是同步的,而StringBuilder
不是。 虽然StringBuilder
比StringBuffer
快,但性能的差异很小。 StringBuilder
是一个SUN的替代StringBuffer
。 它只是避免了所有公共方法的同步。 而不是,它们的function是一样的。
良好用法的例子:
如果你的文本将被改变,并被多个线程使用,那么最好使用StringBuffer
。 如果你的文本要改变,但被单个线程使用,那就使用StringBuilder
。
的StringBuffer
StringBuffer是可变的,意味着可以改变对象的值。 通过StringBuffer创build的对象存储在堆中。 StringBuffer与StringBuilder具有相同的方法,但是StringBuffer中的每个方法都是同步的,即StringBuffer是线程安全的。
因为这样它不允许两个线程同时访问相同的方法。 每个方法一次可以被一个线程访问。
但是由于线程安全属性,因此线程安全也有缺点,因为StringBuffer的性能。 因此,在调用每个类的相同方法时,StringBuilder比StringBuffer快。
StringBuffer的值可以被改变,这意味着它可以被分配给新的值。 如今它是一个最常见的面试问题,上述类别之间的差异。 可以使用toString()方法将string缓冲区转换为string。
StringBuffer demo1 = new StringBuffer(“Hello”) ; // The above object stored in heap and its value can be changed . demo1=new StringBuffer(“Bye”); // Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder的
StringBuilder与StringBuffer相同,即将对象存储在堆中,也可以进行修改。 StringBuffer和StringBuilder的主要区别是StringBuilder也不是线程安全的。 StringBuilder速度很快,因为它不是线程安全的。
StringBuilder demo2= new StringBuilder(“Hello”); // The above object too is stored in the heap and its value can be modified demo2=new StringBuilder(“Bye”); // Above statement is right as it modifies the value which is allowed in the StringBuilder
资源: string与StringBuilder Vs StringBuilder
StringBuffer – 因此同步线程安全 – 因此线程安全缓慢 –
StringBuilder – 在java 5.0中引入 – asynchronous因此快速和高效 – 用户明确需要同步它,如果他愿意的话 – 你可以replace它将StringBuilder没有任何其他的改变
javadoc解释了不同之处:
这个类提供了一个与StringBuffer兼容的API,但是不保证同步。 这个类被devise为在单个线程正在使用string缓冲区的地方(如通常情况下)用作StringBuffer的embedded式replace。 在可能的情况下,build议将此类优先用于StringBuffer,因为在大多数实现中它将更快。
String
是不可变的。
StringBuffer
是一个可变的,同步的。
StringBuilder
也是可变的,但不同步。
StringBuilder
(在Java 5中引入)与StringBuffer
相同,只是它的方法不同步。 这意味着它比后者具有更好的性能,但缺点是它不是线程安全的。
阅读教程了解更多详情。
StringBuilder比StringBuffer快得多,因为它不是同步的。
在这里,您可以更好地了解同步的成本
让我们以编程方式看看比StringBuffer快多lessStringBuilder
public class Test{ public static void main(String[] args){ long startTime = System.currentTimeMillis(); StringBuffer sb = new StringBuffer("Yasir"); for (int i=0; i<10000; i++){ sb.append("Shabbir"); } System.out.println("Time taken by StringBuffer: " + (System.currentTimeMillis() - startTime) + "ms"); startTime = System.currentTimeMillis(); StringBuilder sb2 = new StringBuilder("Yasir"); for (int i=0; i<10000; i++){ sb2.append("Shabbir"); } System.out.println("Time taken by StringBuilder: " + (System.currentTimeMillis() - startTime) + "ms"); } }
产量
StringBuffer花费的时间:16ms
StringBuilder占用的时间:0ms
一个说明StringBuffer和StringBuilder之间区别的简单程序:
/** * Run this program a couple of times. We see that the StringBuilder does not * give us reliable results because its methods are not thread-safe as compared * to StringBuffer. * * For example, the single append in StringBuffer is thread-safe, ie * only one thread can call append() at any time and would finish writing * back to memory one at a time. In contrast, the append() in the StringBuilder * class can be called concurrently by many threads, so the final size of the * StringBuilder is sometimes less than expected. * */ public class StringBufferVSStringBuilder { public static void main(String[] args) throws InterruptedException { int n = 10; //*************************String Builder Test*******************************// StringBuilder sb = new StringBuilder(); StringBuilderTest[] builderThreads = new StringBuilderTest[n]; for (int i = 0; i < n; i++) { builderThreads[i] = new StringBuilderTest(sb); } for (int i = 0; i < n; i++) { builderThreads[i].start(); } for (int i = 0; i < n; i++) { builderThreads[i].join(); } System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length()); //*************************String Buffer Test*******************************// StringBuffer sb2 = new StringBuffer(); StringBufferTest[] bufferThreads = new StringBufferTest[n]; for (int i = 0; i < n; i++) { bufferThreads[i] = new StringBufferTest(sb2); } for (int i = 0; i < n; i++) { bufferThreads[i].start(); } for (int i = 0; i < n; i++) { bufferThreads[i].join(); } System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length()); } } // Every run would attempt to append 100 "A"s to the StringBuilder. class StringBuilderTest extends Thread { StringBuilder sb; public StringBuilderTest (StringBuilder sb) { this.sb = sb; } @Override public void run() { for (int i = 0; i < 100; i++) { sb.append("A"); } } } //Every run would attempt to append 100 "A"s to the StringBuffer. class StringBufferTest extends Thread { StringBuffer sb2; public StringBufferTest (StringBuffer sb2) { this.sb2 = sb2; } @Override public void run() { for (int i = 0; i < 100; i++) { sb2.append("A"); } } }
StringBuffer
是同步的,但StringBuilder
不是。 因此, StringBuilder
比StringBuffer
快。
StringBuffer是可变的。 它可以改变长度和内容。 StringBuffers是线程安全的,这意味着它们具有同步方法来控制访问,以便一次只有一个线程可以访问StringBuffer对象的同步代码。 因此,在multithreading环境中,StringBuffer对象通常是安全的,因为multithreading可能试图同时访问同一个StringBuffer对象。
StringBuilder StringBuilder类与StringBuffer非常相似,只是它的访问不是同步的,所以它不是线程安全的。 通过不同步,StringBuilder的性能可以比StringBuffer好。 因此,如果您正在单线程环境中工作,则使用StringBuilder而不是StringBuffer可能会导致性能提高。 对于其他情况也是如此,例如只有一个线程访问StringBuilder对象的StringBuilder局部variables(即方法内的variables)。
的StringBuffer
StringBuffer是可变的,意味着可以改变对象的值。 通过StringBuffer创build的对象存储在堆中。 StringBuffer与StringBuilder具有相同的方法,但是StringBuffer中的每个方法都是同步的,即StringBuffer是线程安全的。
StringBuilder的
StringBuilder与StringBuffer相同,即将对象存储在堆中,也可以进行修改。 StringBuffer和StringBuilder的主要区别在于StringBuilder不是线程安全的。 StringBuilder速度很快,因为它不是线程安全的。
StringBuffer用于存储将被更改的string(String对象不能被更改)。 它会根据需要自动扩展。 相关类:String,CharSequence。
StringBuilder是在Java 5中添加的。它与StringBuffer在所有方面都是相同的,除非它不同步,这意味着如果多个线程同时访问它,可能会有麻烦。 对于单线程程序来说,最常见的情况是,避免同步的开销使得StringBuilder的速度稍快一些。
更好的使用StringBuilder,因为它不同步,因此性能更好。 StringBuilder是旧的StringBuffer的一个替代品。
StringBuffer的:
- multithreading
- 同步
- 比StringBuilder慢
StringBuilder的
- 单线程
- 未同步
- 比以前更快的string
这个链接不仅可以让你理解StringBuilder
和StringBuffer
的概念,还可以理解它们与String
类的联系和区别。 这会让你明白什么时候使用哪个类。 http://www.acquireandinspire.org/2013/01/string-string-builder-string-buffer.html
在StringBuilder和StringBuffer之间没有本质区别,只是它们之间存在一些差异。 在StringBuffer中,这些方法是同步的。 这意味着一次只有一个线程可以对它们进行操作。 如果有多个线程,那么第二个线程将不得不等待第一个线程完成,第三个线程将不得不等待第一个线程完成,等等。 这使得这个过程非常缓慢,因此在StringBuffer情况下的性能很低。
另一方面,StringBuilder是不同步的。 这意味着一次有多个线程可以同时在同一个StrinBuilder对象上运行。 这使得这个过程非常快,因此StringBuilder的性能很高。
检查StringBuffer
的同步追加方法和StringBuffer
非同步追加方法的内部。
StringBuffer :
public StringBuffer(String str) { super(str.length() + 16); append(str); } public synchronized StringBuffer append(Object obj) { super.append(String.valueOf(obj)); return this; } public synchronized StringBuffer append(String str) { super.append(str); return this; }
StringBuilder :
public StringBuilder(String str) { super(str.length() + 16); append(str); } public StringBuilder append(Object obj) { return append(String.valueOf(obj)); } public StringBuilder append(String str) { super.append(str); return this; }
由于append是synchronized
, StrinbBuilder
在multithreading情况下,与StrinbBuilder
相比, StringBuffer
具有性能开销。 只要你不在多个线程之间共享缓冲区,使用StringBuilder
,由于在append方法中没有synchronized
,所以速度很快。
由于StringBuffer
是同步的,因此需要额外的努力,因此基于性能,它比StringBuilder
慢一点。
string生成器 :
int one = 1; String color = "red"; StringBuilder sb = new StringBuilder(); sb.append("One=").append(one).append(", Color=").append(color).append('\n'); System.out.print(sb); // Prints "One=1, Colour=red" followed by an ASCII newline.
string缓冲区
StringBuffer sBuffer = new StringBuffer("test"); sBuffer.append(" String Buffer"); System.out.println(sBuffer);
build议尽可能使用StringBuilder,因为它比StringBuffer快。 但是,如果线程安全是必要的,最好的select是StringBuffer对象。
string是一个不可变的对象,这意味着在StringBuffer是可变的地方值不能被改变。
StringBuffer是Synchronized的,因此线程安全,因为StringBuilder不是,只适用于单线程实例。
StringBuffer中的每个方法都是Synchronized。 因此一次只允许一个线程操作StringBuffer对象。 它增加了一个线程的等待时间,并创build性能问题来克服这个问题SUN人们在1.5版本中引入了StringBuilder。