回答

26

StringBuffers是线程安全的,这意味着他们已经同步方法来控制访问,以便只有一个线程可以同时访问一个StringBuffer对象的同步代码。因此,在多线程环境中,StringBuffer对象通常是安全的,因为多线程可能试图同时访问同一个StringBuffer对象。

StringBuilder's访问不是同步的,这样它不是线程安全的。通过不同步,StringBuilder的性能可以优于StringBuffer。因此,如果您正在单线程环境中工作,则使用StringBuilder而不是StringBuffer可能会提高性能。对于其他情况也是如此,例如只有一个线程访问StringBuilder对象的StringBuilder局部变量(即方法内的变量)。

所以,喜欢StringBuilder因为,

  • 小的性能提升。
  • StringBuilder是StringBuffer类的1:1替代品。
  • StringBuilder的是不是线程同步,因此执行Java的
  • 的大多数实现更好

检查了这一点:

+0

最好说StringBuffer是“线程安全的”,但它很容易调整两个线程竞争相同的缓冲区导致竞争条件。即使您需要在线程之间共享字符串缓冲区,您很可能需要对其执行更高级别的控制,而不是它所显示的同步方法。因此,除非第三方库要求您使用StringBuffer,否则不能考虑使用StringBuffer的很多理由,或者为了传统/小众目的。 – locka 2014-03-28 10:48:06

+0

'StringBuilder'并不完全是'StringBuffer'的1:1替代品。例如,Matcher的appendReplacement方法需要一个StringBuffer作为它的第一个参数。 – 2018-01-09 21:19:42

7

StringBuilder的应该是一个(微小)快一点,因为它是不同步的(线程安全)。

您可以注意到真正沉重的应用程序中的差异。

由于StringBuilder类支持所有相同的操作,但它的速度更快,因为它不执行同步,所以通常应该优先使用StringBuilder类。

http://download.oracle.com/javase/6/docs/api/java/lang/StringBuffer.html

+0

请再次阅读此问题... – 2011-05-30 09:20:01

+0

@MANISH PATHAK - 请阅读答案 - 问题:为什么要使用StringBuilder? - 答案:StringBuilder应该是一个(微小的)位更快一点(第一句 – 2011-05-30 09:49:50

+3

澄清:即使一个线程正在使用对象,synchronized方法也会强制线程获取并释放每个访问的监视器。这可能会减慢程序。 – Jonathan 2011-05-30 10:53:39

2

StringBuilder具有更好的性能,因为它的方法是不同步的。

所以,如果你不需要同时建立一个字符串(这是一个相当非典型scenarion反正),那么就没有必要“支付”了不必要的同步开销。

+0

你可以描述这种情况吗? – 2011-05-30 09:22:51

+1

@Manish - 不,我不能,因为实际上我无法想象一个场景,我不得不选择StringBuffer而不是StringBuilder。 – 2011-05-30 10:56:49

+0

谢谢安德烈亚斯... 我从上面的帖子了解它。 感谢所有 – 2011-05-30 12:57:36

3

StringBuffer在单线程应用程序中。它的工作方式和StringBuilder一样。

唯一的区别是通过具有所有同步方法添加的微小开销,这在单线程应用程序中没有任何优势。

我的看法是,主要原因StringBuilder引入的是,编译器使用StringBuffer(现在StringBuilder),当它编译包含String级联码:在这种情况下同步从未必要的和更换所有的具有非同步StringBuilder的地方可以提供较小的性能改进。

4

在多个线程中使用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这样的类。

0

这将帮助u人, 是直Builder是不是缓冲速度更快,

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 -> 
0

马尼什,虽然只有一个线程在您的StringBuffer实例运行着,在获取和释放监视器一些开销无论何时调用其任何方法,都会锁定StringBuffer实例。因此StringBuilder是单线程环境中的首选。

0

同步对象的成本很高。没有将程序看作是独立的实体;当你阅读概念并将它们应用于你的问题细节中提到的小程序时,它不是问题,当我们想要扩展系统时会出现问题。在这种情况下,您的单线程程序可能依赖于其他几个方法/程序/实体,因此同步对象在性能方面会导致严重的编程复杂性。所以如果你确定没有必要同步一个对象,那么你应该使用StringBuilder,因为这是一个很好的编程习惯。最后,我们想要学习编程来制作可扩展的高性能系统,所以这就是我们应该做的!

相关问题