Java StringBuilder和StringBuffer之间的区别

Java StringBuilder和StringBuffer之间的区别,java,stringbuilder,stringbuffer,Java,Stringbuilder,Stringbuffer,StringBuffer和StringBuilder之间的主要区别是什么? 在决定这些方法中的任何一种时是否存在性能问题?是同步的,而不是。基本上,StringBuffer方法是同步的,而StringBuilder是不同步的 这些操作“几乎”相同,但在单个线程中使用同步方法是过分的 差不多就是这样 引自: 此类[StringBuilder]提供与StringBuffer兼容的API,但不保证同步。此类被设计为在单个线程使用字符串缓冲区的地方(通常情况下)作为StringBuffer的插入式替换。

StringBuffer
StringBuilder
之间的主要区别是什么?
在决定这些方法中的任何一种时是否存在性能问题?

是同步的,而不是。

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

这些操作“几乎”相同,但在单个线程中使用同步方法是过分的

差不多就是这样

引自:

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

所以它被用来代替它


同样的情况也发生在
Vector
ArrayList

中,StringBuilder是在Java1.5中引入的,因此它不适用于早期的JVM

从:

StringBuilder类提供与StringBuffer兼容的API,但不保证同步。此类被设计为在单个线程使用字符串缓冲区的地方(通常情况下)作为StringBuffer的插入式替换。在可能的情况下,建议优先使用该类而不是StringBuffer,因为在大多数实现中它会更快


StringBuilder不是线程安全的。字符串缓冲区为。更多信息


编辑:至于性能,在启动后,StringBuilder是赢家。但是,对于较小的迭代,性能差异可以忽略不计。

StringBuffer

  • 同步线程安全
  • 线程安全,因此速度较慢
StringBuilder

  • 在Java5.0中引入
  • 异步,因此快速高效
  • 如果用户愿意,他需要显式地同步它
  • 您可以将其替换为
    StringBuffer
    ,而无需任何其他更改

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


StringBuilder是在Java5中添加的。它在所有方面都与StringBuffer相同,只是它不同步,这意味着如果多个线程同时访问它,可能会出现问题。对于单线程程序,最常见的情况是,避免同步开销会使StringBuilder的速度略微加快。

StringBuffer
是同步的,但
StringBuilder
不是。因此,
StringBuilder
StringBuffer

快,因为它不是
同步的

下面是一个简单的基准测试:

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

A给出了
StringBuffer
2241ms
StringBuilder

753ms
的数值
A
String
是一个不可变的对象,这意味着值不能更改,而
StringBuffer
是可变的


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

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

良好使用示例:


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

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

的一种替代品,它解释了这种差异:

此类提供与StringBuffer兼容的API,但不保证同步。此类被设计为在单个线程使用字符串缓冲区的地方(通常情况下)作为StringBuffer的插入式替换。在可能的情况下,建议优先使用该类而不是StringBuffer,因为在大多数实现中它会更快


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

阅读更多细节

但是需要借助一个例子来获得明显的区别吗

StringBuffer或StringBuilder

只需使用
StringBuilder
,除非您确实试图在线程之间共享缓冲区
StringBuilder
是原始同步的
StringBuffer
类的未同步(开销更小=效率更高)的弟弟。

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


StringBuilder
后来才出现。
StringBuffer
的大多数使用都是单线程的,不必要地支付了同步的成本

因为
字符串
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));
}
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);
    }
}
/**
 * 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");
        }

    }
}
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 is not synchronized 
 StringBuilder is not thread-safe
 StringBuilder performance is better than 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;
}
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;
}
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 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
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);  
private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test

int loop = 100000;
long start = 0;

// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
  str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");

// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
  sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");

// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
  sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");

  }
String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms
String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms