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
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
的数值AString
是一个不可变的对象,这意味着值不能更改,而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