StringBuffer和StringBuilder之间的主要区别是什么?在决定其中任何一项时是否存在性能问题?
当前回答
在单线程中,由于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!
因此,构建器比缓冲区更快,比字符串串联更快。现在让我们为多个线程使用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需要157毫秒才能完成100000次追加。这不是同一个测试,但与之前的37毫秒相比,您可以放心地假设,使用多线程时,StringBuffers追加的速度较慢。原因是JIT/hotspot/compiler/something在检测到不需要检查锁时会进行优化。
但是对于StringBuilder,您有java.lang.ArrayIndexOutOfBoundsException,因为并发线程试图在不应该添加的地方添加一些内容。
结论是,您不必追逐StringBuffers。如果您有线程,在尝试获得几纳秒之前,请考虑它们正在做什么。
其他回答
StringBuilder不是线程安全的。字符串缓冲区是。更多信息请点击此处。
编辑:至于性能,在热点启动后,StringBuilder是赢家。然而,对于较小的迭代,性能差异可以忽略不计。
StringBuffer已同步,StringBuilder未同步。
由于StringBuffer是同步的,因此需要额外的工作,因此基于性能,它比StringBuilder慢一点。
字符串是不可变的。
StringBuffer是一个可变的和同步的。
StringBuilder也是可变的,但不同步。
首先让我们看看相似之处:StringBuilder和StringBuffer都是可变的。这意味着您可以在同一位置更改它们的内容。
差异:StringBuffer也是可变的和同步的。其中,作为StringBuilder是可变的,但默认情况下不同步。
同步(synchronization)的含义:当某些东西被同步时,多个线程可以访问并修改它,而不会产生任何问题或副作用。StringBuffer是同步的,因此您可以在多个线程中使用它,而不会出现任何问题。
何时使用哪一个?StringBuilder:当您需要一个可以修改的字符串,并且只有一个线程在访问和修改它时。StringBuffer:当您需要一个可以修改的字符串,并且多个线程正在访问和修改它时。
注意:不要不必要地使用StringBuffer,也就是说,如果只有一个线程在修改和访问它,就不要使用它,因为它有很多用于同步的锁定和解锁代码,这将不必要地占用CPU时间。除非需要,否则不要使用锁。
推荐文章
- 如何格式化Joda-Time DateTime仅为mm/dd/yyyy?
- 如何在POM.xml中引用环境变量?
- 如何在android中复制一个文件?
- 将整数转换为字符串,以逗号表示千
- 接口方法的最终参数-有什么意义?
- Java中的@UniqueConstraint注释
- 如何在清洁模式下运行eclipse ?如果我们这样做会发生什么?
- 获取java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory异常
- Java中的正则表达式命名组
- c#和Java的主要区别是什么?
- 什么是NullPointerException,我如何修复它?
- 在Java中使用“final”修饰符
- 无法在Flutter上找到捆绑的Java版本
- 如何在Kotlin解析JSON ?
- 如何在新的材质主题中改变背面箭头的颜色?