提问



StringBufferStringBuilder之间的主要区别是什么?
在决定其中任何一个时,是否存在任何性能问题?

最佳参考


StringBuffer是同步的,StringBuilder不是。[76] [77]

其它参考1


StringBuilderStringBuffer快,因为它不是synchronized[78] [79]


这是一个简单的基准测试:


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);
        }
    }
}


测试运行给出了StringBufferStringBuilder2241 ms StringBuilder ArrayList的数量[[。[80]

其它参考2


基本上,StringBuffer方法是同步的,而StringBuilder则不是。


操作几乎相同,但在单个线程中使用同步方法是过度的。


这几乎就是它。


从StringBuilder API引用:[81]



  此类[[StringBuilder]]提供与StringBuffer兼容的API,但不保证同步。此类设计用作StringBuffer的替代品,用于单个线程使用字符串缓冲区的位置(通常情况下)。在可能的情况下,建议使用此类优先于StringBuffer,因为在大多数实现中它会更快。



所以它是替代它。


VectorArrayList也是如此。

其它参考3



  但是需要借助一个例子来获得明显的差异?

  
  StringBuffer或StringBuilder



除非您真的想在线程之间共享缓冲区,否则只需使用StringBuilderStringBuilder是原始synchronized StringBuffer类的未经同步(开销较小=效率更高)的弟弟。


StringBuffer排在第一位。 Sun在所有条件下都关注正确性,因此他们将其同步以使其成为线程安全以防万一。


StringBuilder后来来了。 StringBuffer的大多数用途是单线程,并且不必要地支付同步的成本。


由于StringBuilder是没有同步的StringBuffer 插入式替换 ,因此任何示例之间都不会有差异。


如果 尝试在线程之间共享,则可以使用StringBuffer,但要考虑是否需要更高级别的同步,例如或许不使用StringBuffer,您应该同步使用StringBuilder的方法。

其它参考4


首先让我们看一下相似之处:
StringBuilder和StringBuffer都是可变的。这意味着您可以在同一位置更改它们的内容。


差异:
StringBuffer也是可变的和同步的。 StringBuilder是可变的,但默认情况下不同步。


同步(同步)的含义:
当某些东西同步时,多个线程可以访问,并修改它而不会出现任何问题或副作用。
StringBuffer是同步的,因此您可以将它与多个线程一起使用而不会出现任何问题。


使用哪一个?
StringBuilder:当你需要一个可以修改的字符串时,只有一个线程正在访问和修改它。
StringBuffer:当你需要一个可以修改的字符串,并且多个线程正在访问和修改它。


注意:不要不必要地使用StringBuffer,即如果只有一个线程正在修改和访问它,就不要使用它,因为它有很多锁定和解锁代码用于同步,这将不必要地占用CPU时间。除非有必要,否则不要使用锁。

其它参考5


在单线程中,由于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 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对于100000个追加采用 157 ms 。这不是相同的测试,但与之前的37 ms相比,你可以放心地假设使用多线程时StringBuffers追加速度较慢。原因是JIT/hotspot/compiler/something会进行优化当它检测到 no 需要检查锁时。


但是使用StringBuilder,你有java.lang.ArrayIndexOutOfBoundsException ,因为并发线程试图添加不应该的东西。


结论是你不必追逐StringBuffers。在你有线程的地方,在尝试获得几纳秒之前考虑一下他们在做什么。

其它参考6


StringBuilder是在Java 1.5中引入的,因此它不能使用早期的JVM。


来自Javadocs:[82]



  StringBuilder类提供与StringBuffer兼容的API,但不保证同步。此类设计用作StringBuffer的替代品,用于单个线程使用字符串缓冲区的位置(通常情况下)。在可能的情况下,建议首先使用此类优先于StringBuffer,因为在大多数实现中它会更快。


其它参考7



  很好的问题



以下是差异,我注意到:


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.


常见的事情: -



  两者具有相同的具有相同签名的方法。两者都是可变的。


其它参考8


StringBuilder不是线程安全的。 String Buffer是。更多信息在这里。[83]


编辑:至于性能,热点开始后,StringBuilder是赢家。但是,对于小的迭代,性能差异可以忽略不计。[84]

其它参考9


StringBuilderStringBuffer几乎相同。区别在于StringBuffer是同步的,StringBuilder不是。虽然StringBuilderStringBuffer快,但性能差异很小。 StringBuilder是SUN的StringBuffer的替代品。它只是避免了所有公共方法的同步。而不是那样,它们的功能是相同的。


良好用法示例:


如果您的文本将要更改并由多个线程使用,那么最好使用StringBuffer。如果您的文本将更改但由单个线程使用,则使用StringBuilder

其它参考10


的StringBuffer


StringBuffer是可变的,意味着可以更改对象的值。通过StringBuffer创建的对象存储在堆中。 StringBuffer与StringBuilder具有相同的方法,但StringBuffer中的每个方法都是同步的,即StringBuffer是线程安全的。


因此,它不允许两个线程同时访问同一个方法。每个方法一次可以由一个线程访问。


但是线程安全也有缺点,因为StringBuffer的性能由于线程安全属性而命中。因此,当调用每个类的相同方法时,StringBuilder比StringBuffer更快。


StringBuffer值可以更改,这意味着它可以分配给新值。如今它是一个最常见的面试问题,上述课程之间的差异。
String Buffer可以通过使用转换为字符串
toString()方法。


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


[85]


资源:String Vs StringBuffer与StringBuilder [86]

其它参考11


StringBuffer



  • 同步线程安全

  • 线程安全因此很慢

  •   -


StringBuilder



  • 在Java 5.0中引入

  • 异步因此快速&高效

  • 用户明确需要同步它,如果他想要

  • 您可以StringBuilder替换它而不做任何其他更改


其它参考12


String是不可改变的。


StringBuffer是一个可变和同步的。


StringBuilder也是可变的,但不同步。

其它参考13


javadoc解释了差异:[87]



  此类提供与StringBuffer兼容的API,但不保证同步。此类设计用作StringBuffer的替代品,用于单个线程使用字符串缓冲区的位置(通常情况下)。在可能的情况下,建议首先使用此类优先于StringBuffer,因为在大多数实现中它会更快。


其它参考14


StringBuilder(在Java 5中引入)与StringBuffer相同,除了它的方法不同步。这意味着它具有比后者更好的性能,但缺点是它不是线程安全的。


阅读教程了解更多详情。[88]

其它参考15


StringBuilder比StringBuffer快得多,因为它是非同步的。


在这里你对同步的成本有了更多的了解


让我们以编程方式看看StringBuilder比StringBuffer快多少


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所花费的时间:16毫秒


StringBuilder花费的时间:0ms

其它参考16


一个简单的程序,说明了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");
        }

    }
}

其它参考17


更好地使用StringBuilder,因为它不是同步的,因此性能更好。 StringBuilder是旧StringBuffer的替代品。

其它参考18


StringBuffer是同步的,但StringBuilder不是。结果,StringBuilderStringBuffer快。

其它参考19


的StringBuffer
是可变的。它可以在长度和内容方面发生变化。 StringBuffers是线程安全的,这意味着它们具有控制访问的同步方法,因此一次只能有一个线程访问StringBuffer对象的同步代码。因此,StringBuffer对象通常可以安全地在多线程环境中使用线程可能正在尝试同时访问同一个StringBuffer对象。


的StringBuilder
StringBuilder类与StringBuffer非常相似,只是它的访问不同步,因此它不是线程安全的。通过不同步,StringBuilder的性能可以比StringBuffer更好。因此,如果您在单线程环境中工作,则使用StringBuilder而不是StringBuffer可能会提高性能。对于其他情况也是如此,例如StringBuilder局部变量(即方法中的变量),其中只有一个线程将访问StringBuilder对象。

其它参考20


的StringBuffer


StringBuffer是可变的,意味着可以更改对象的值。通过StringBuffer创建的对象存储在堆中。 StringBuffer与StringBuilder具有相同的方法,但StringBuffer中的每个方法都是同步的,即StringBuffer是线程安全的。


的StringBuilder


StringBuilder与StringBuffer相同,即它将对象存储在堆中,也可以对其进行修改。 StringBuffer和StringBuilder之间的主要区别在于StringBuilder不是线程安全的。
StringBuilder很快,因为它不是线程安全的。

其它参考21


的StringBuffer:



  • 多线程

  • 同步

  • 比StringBuilder慢



的StringBuilder



  • 单线程

  • 不同步化

  • 比以往更快的字符串


其它参考22


String-Builder :


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.


字符串缓冲区


StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);  


建议尽可能使用StringBuilder,因为它比StringBuffer更快。但是,如果需要线程安全性,则最好的选项是StringBuffer对象。

其它参考23


StringBuffer用于存储将被更改的字符串(不能更改String对象)。它会根据需要自动扩展。相关类:String,CharSequence。


StringBuilder是在Java 5中添加的。它在所有方面都与StringBuffer相同,只是它没有同步,这意味着如果多个线程同时访问它,可能会有麻烦。对于单线程程序,最常见的情况是,避免同步开销会使StringBuilder的速度稍微快一些。

其它参考24


StringBuilder和StringBuffer之间没有基本的区别,它们之间只存在一些差异。在StringBuffer中,方法是同步的。这意味着一次只有一个线程可以对它们进行操作。如果有多个线程,则第二个线程必须等待第一个线程完成,第三个线程必须等待第一个和第二个线程完成,依此类推。这使得该过程非常慢,因此在StringBuffer的情况下性能很低。


另一方面,StringBuilder是非同步的。这意味着多个线程可以同时在同一个StrinBuilder对象上运行。这使得该过程非常快,因此StringBuilder的性能很高。

其它参考25


检查StringBuffer的同步追加方法和StringBuilder的非同步追加方法的内部。


StringBuffer的:[90]


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的:[91]


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是synchronizedStringBuffer与多线程场景中的StrinbBuilder相比具有性能开销。只要您不在多个线程之间共享缓冲区,请使用StringBuilder,由于在追加方法中没有synchronized而这很快。

其它参考26


由于StringBuffer是同步的,它需要一些额外的努力,因此基于perforamance,它比StringBuilder慢一点。

其它参考27


String是一个不可变对象,这意味着在StringBuffer可变的情况下不能更改该值。


StringBuffer是同步的,因此线程安全,而StringBuilder不适用于单线程实例。

其它参考28


这个链接不仅可以让你理解StringBuilderStringBuffer的概念,还可以理解它们与String类的联系和区别。这将使您了解何时使用哪个类。
http://www.acquireandinspire.org/2013/01/string-string-builder-string-buffer.html[92]

其它参考29


主要区别是StringBuffer是同步的,但StringBuilder不是。如果你需要使用多个线程,那么建议使用StringBuffer。但是,根据执行速度StringBuilder要快于StringBuffer,因为它不同步。