Java StringBuilder и безопасность потоков - PullRequest
13 голосов
/ 10 марта 2009

Я строю строку из нескольких частей и хочу использовать для этого либо 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. Из документации я не могу точно решить, считается ли это использованием нескольких потоков или нет.

Ответы [ 5 ]

19 голосов
/ 10 марта 2009

Это прекрасно. Локальные переменные не имеют проблем с безопасностью потоков, если они не обращаются к переменным экземпляра или класса или не изменяют их.

11 голосов
/ 10 марта 2009

Да, это безопасно, поскольку объект StringBuilder используется только локально (каждый поток, вызывающий foo (), создаст свой собственный StringBuilder).

Вы также должны заметить, что отправленный вами код практически идентичен байт-коду, сгенерированному следующим образом:

String foo(String a, String b) {
    return a + b;
}
6 голосов
/ 11 марта 2009

Код у вас в безопасности.

Этот код не является.

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);
    }
}

Локальные переменные, использующие только локальные данные, не имеют проблем с безопасностью потоков. Проблемы с безопасностью потоков могут возникнуть только после того, как вы начнете работать с данными, видимыми на уровне класса / метода экземпляра / уровня переменной.

4 голосов
/ 10 марта 2009

Согласитесь с другими ответами - просто записка.

Если бы был случай, когда StringBuffer использовался несколькими потоками, это, вероятно, полностью неиспользуемый вариант использования, потому что это означало бы, что одна строка строилась в квазислучайном порядке, поэтому не было бы смысла сделать поток StringBuffer безопасным.

3 голосов
/ 10 марта 2009

Я не уверен, нужен ли этот код, потому что Java, я думаю, автоматически выбирает StringBuilder. Если у вас нет проблем с производительностью, нажмите + b.

В случае необходимости производительности попробуйте:

return new StringBuilder(
a.length() + b.length()).append(a).append(b).toString();

Он правильно определяет размер буфера и не позволяет виртуальной машине изменять его размер и создавать мусор для сбора в пути.

...