Java StringBuilder和线程安全

时间:2009-03-10 18:26:53

标签: java multithreading thread-safety stringbuilder

我正在使用多个部分构建一个字符串,并希望使用StringBufferStringBuilder来执行此操作。从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的单独实例。从文档中,我无法确定这是否算作多线程的使用。

5 个答案:

答案 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调整大小并在途中创建垃圾以进行收集。