StringBuffer和StringBuilder之间的主要区别是什么?在决定其中任何一项时是否存在性能问题?
当前回答
字符串缓冲区:
多线程已同步比StringBuilder慢
字符串拼接
单线程未同步比以往更快的字符串
其他回答
字符串缓冲区:
多线程已同步比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的替代品。
StringBuffer是线程安全的,但StringBuilder不是线程安全的。StringBuilder比StringBuffer更快。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);
}
}
}
测试运行得出StringBuffer为2241ms,StringBuilder为753ms。
推荐文章
- 如何分割逗号分隔的字符串?
- Java字符串—查看字符串是否只包含数字而不包含字母
- Mockito.any()传递带有泛型的接口
- 在IntelliJ 10.5中运行测试时,出现“NoSuchMethodError: org.hamcrest. matcher . descripbemismatch”
- 使用String.split()和多个分隔符
- Java数组有最大大小吗?
- 在Android中将字符串转换为Uri
- 从JSON生成Java类?
- 为什么java.util.Set没有get(int index)?
- Swing和AWT的区别是什么?
- 为什么Java流是一次性的?
- 四舍五入BigDecimal *总是*有两位小数点后
- 设计模式:工厂vs工厂方法vs抽象工厂
- Java:检查enum是否包含给定的字符串?
- 它的意思是:序列化类没有声明一个静态的最终serialVersionUID字段?