Подтвердить что ты не робот

Java StringBuilder и безопасность потоков

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

Любая помощь, чтобы разъяснить это, будет оценена.

4b9b3361

Ответ 1

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

Ответ 2

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

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

String foo(String a, String b) {
    return a + b;
}

Ответ 3

Код, который у вас есть, безопасен.

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

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

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

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

Ответ 5

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

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

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

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