我正在使用多个部分构建一个字符串,并希望使用StringBuffer
或StringBuilder
来执行此操作。从Java 5文档中,我看到StringBuilder
在可能的情况下是首选,但需要注意
StringBuilder
的实例不适合多线程使用。
从这个陈述中,我理解我不应该有多个线程共享的单个StringBuilder
实例。但是这个案子呢:
//Is this safe?
//foo() is called simultaneously by multiple threads
String foo(String a, String b) {
return new StringBuilder(a).append(b).toString();
}
这里可能同时在函数中有多个线程,同时使用StringBuilder
类(例如,静态变量的并发访问,如果有的话),但每个线程都有它的拥有StringBuilder
的单独实例。从文档中,我无法确定这是否算作多线程的使用。
答案 0 :(得分:19)
这很好。局部变量在线程安全性方面没有问题,只要它们不访问或改变实例或类变量。
答案 1 :(得分:11)
是的,这是安全的,因为StringBuilder对象仅在本地使用(每个调用foo()的线程都会生成自己的StringBuilder。)
您还应该注意,您发布的代码几乎与此处生成的字节代码完全相同:
String foo(String a, String b) {
return a + b;
}
答案 2 :(得分:6)
您拥有的代码是安全的。
此代码不是。
public class Foo
{
// safe
private final static StringBuilder builder;
public static void foo()
{
// safe
builder = new StringBuilder();
}
public static void foo(final String a)
{
// unsafe
builder.append(a);
}
public synchronized void bar(final String a)
{
// safe
builder.append(a);
}
}
仅使用本地数据的局部变量没有线程安全问题。一旦开始处理在类或实例方法/变量级别可见的数据,您就只能遇到线程安全问题。
答案 3 :(得分:4)
同意其他答案 - 只是一张纸条。
如果有多个线程正在使用StringBuffer的情况,那么它可能是一个完全破坏的用例,因为它意味着单个字符串是以准随机顺序构建的,所以它没有意义使StringBuffer线程安全。
答案 4 :(得分:3)
我不确定是否需要此代码,因为Java我自动选择了StringBuilder。如果您没有性能问题,请使用+ b。
如果有性能需求,请尝试:
return new StringBuilder(
a.length() + b.length()).append(a).append(b).toString();
它正确调整缓冲区的大小,并防止VM调整大小并在途中创建垃圾以进行收集。