StringBuffer
和之间的主要区别是StringBuilder
什么?在决定其中任何一个时,是否存在任何性能问题?
StringBuffer
是同步的,StringBuilder
不是.
StringBuilder
比不是StringBuffer
因为它更快synchronized
.
这是一个简单的基准测试:
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 ; i--) { sb.append(""); } System.out.println(System.currentTimeMillis() - t); } } }
一个试运行给出的数字2241 ms
为StringBuffer
VS 753 ms
的StringBuilder
.
基本上,StringBuffer
方法是同步的,而StringBuilder
不是.
这些操作"几乎"相同,但在单个线程中使用同步方法是过度的.
这几乎就是它.
从StringBuilder API引用:
此类[StringBuilder]提供与StringBuffer兼容的API,但不保证同步.此类设计用作StringBuffer的替代品,用于单个线程使用字符串缓冲区的位置(通常情况下).在可能的情况下,建议首先使用此类优先于StringBuffer,因为在大多数实现中它会更快.
因此,它取代了它.
同样的事情发生在Vector
和ArrayList
.
但是需要在一个例子的帮助下获得明显的差异?
StringBuffer或StringBuilder
StringBuilder
除非你真的试图在线程之间共享缓冲区,否则简单地使用.StringBuilder
是原始同步StringBuffer
类的未同步(开销较小=效率更高)的弟弟.
StringBuffer
先来了.Sun在所有条件下都关注正确性,因此他们将其同步以使其成为线程安全以防万一.
StringBuilder
后来来了.大多数用途StringBuffer
是单线程,并且不必要地支付同步的成本.
由于StringBuilder
是一个简易替换为StringBuffer
不同步时,就不会有任何的例子之间的差异.
如果你正在尝试线程之间共享,你可以使用StringBuffer
,但考虑更高级别的同步是否是必要的,例如,也许不是使用StringBuffer的问题,您应该同步的是使用StringBuilder方法.
首先让我们看看相似之处:StringBuilder和StringBuffer都是可变的.这意味着您可以在同一位置更改它们的内容.
差异:StringBuffer也是可变的和同步的.StringBuilder可变,但默认情况下不同步.
synchronized(同步)的含义:当某个东西同步时,多个线程可以访问,并修改它而不会出现任何问题或副作用.StringBuffer是同步的,因此您可以将它与多个线程一起使用而不会出现任何问题.
哪一个使用的时候? StringBuilder:当你需要一个可以修改的字符串时,只有一个线程正在访问和修改它.StringBuffer:当你需要一个可以修改的字符串,并且多个线程正在访问和修改它.
注意:不要不必要地使用StringBuffer,即如果只有一个线程正在修改和访问它,请不要使用它,因为它有很多锁定和解锁代码用于同步,这将不必要地占用CPU时间.除非需要,否则不要使用锁.
在单线程中,由于JVM优化,StringBuffer并不比StringBuilder慢得多.在多线程中,您无法安全地使用StringBuilder.
这是我的测试(不是基准,只是测试):
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)); }
结果:
字符串:319740
缓冲区:23
构建器:7!
因此,构建器比Buffers更快,并且比字符串连接更快.现在让我们使用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 AppendableRunnableimplements 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个附加内容.它不是相同的测试,但与之前的37 ms相比,您可以放心地假设使用多线程时StringBuffers追加速度较慢.其原因是,在JIT /热点/编译器/东西使得优化,当它检测到有没有必要检查锁.
但是使用StringBuilder,你有java.lang.ArrayIndexOutOfBoundsException,因为并发线程试图添加它不应该的东西.
结论是您不必追逐StringBuffers.在尝试获得几纳秒之前,在有线程的地方,考虑一下他们在做什么.
StringBuilder是在Java 1.5中引入的,因此它不适用于早期的JVM.
来自Javadocs:
StringBuilder类提供与StringBuffer兼容的API,但不保证同步.此类设计用作StringBuffer的替代品,用于单个线程使用字符串缓冲区的位置(通常情况下).在可能的情况下,建议首先使用此类优先于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 Buffer是.更多信息在这里.
编辑:至于性能,热点开始后,StringBuilder是赢家.但是,对于小的迭代,性能差异可以忽略不计.
StringBuffer
同步因此线程安全
线程安全因此很慢
-
StringBuilder
在Java 5.0中引入
异步因此快速高效
如果他愿意,用户明确需要同步它
您可以替换它StringBuffer
而无需任何其他更改
StringBuilder
而StringBuffer
几乎是相同的.区别在于StringBuffer
同步而StringBuilder
不是.虽然StringBuilder
比速度快StringBuffer
,但性能差异很小.StringBuilder
是SUN的替代品StringBuffer
.它只是避免了所有公共方法的同步.而不是那样,他们的功能是相同的.
良好用法示例:
如果您的文本将要更改并由多个线程使用,那么最好使用它StringBuffer
.如果您的文本将要更改但由单个线程使用,请使用StringBuilder
.
的StringBuffer
StringBuffer是可变的,意味着可以更改对象的值.通过StringBuffer创建的对象存储在堆中.StringBuffer与StringBuilder具有相同的方法,但StringBuffer中的每个方法都是同步的,即StringBuffer是线程安全的.
因此,它不允许两个线程同时访问同一个方法.每个方法一次可以由一个线程访问.
但由于线程安全属性,StringBuffer的性能会受到攻击,因此线程安全也有缺点.因此,当调用每个类的相同方法时,StringBuilder比StringBuffer更快.
StringBuffer值可以更改,这意味着它可以分配给新值.如今它是一个最常见的面试问题,上述课程之间的差异.可以使用toString()方法将String Buffer转换为字符串.
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 Vs StringBuffer与StringBuilder
String
是不可改变的.
StringBuffer
是一个可变和同步的.
StringBuilder
也是可变的,但它不同步.
该javadoc的解释的区别:
此类提供与StringBuffer兼容的API,但不保证同步.此类设计用作StringBuffer的替代品,用于单个线程使用字符串缓冲区的位置(通常情况下).在可能的情况下,建议首先使用此类优先于StringBuffer,因为在大多数实现中它会更快.
StringBuilder
(在Java 5中引入)是相同的StringBuffer
,除了它的方法不同步.这意味着它具有比后者更好的性能,但缺点是它不是线程安全的.
阅读教程了解更多详情.
一个简单的程序,说明了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, i.e. * 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"); } } }