Ответ 1
Это прекрасно. Локальные переменные не имеют проблем с безопасностью потоков, если они не имеют доступа или не изменяют переменные экземпляра или класса.
Я создаю 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. Из документации я не могу решить, относится ли это к использованию несколькими потоками или нет.
Любая помощь, чтобы разъяснить это, будет оценена.
Это прекрасно. Локальные переменные не имеют проблем с безопасностью потоков, если они не имеют доступа или не изменяют переменные экземпляра или класса.
Да, это безопасно, потому что объект StringBuilder используется только локально (каждый поток, вызывающий foo(), генерирует собственный StringBuilder).
Вы также должны заметить, что код, который вы опубликовали, практически идентичен байт-коду, сгенерированному этим:
String foo(String a, String b) {
return a + b;
}
Код, который у вас есть, безопасен.
Этот код не является.
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);
}
}
Локальные переменные, которые используют только локальные данные, не имеют проблем с потокобезопасностью. После того, как вы начнете обрабатывать данные, видимые на уровне класса или экземпляра метода/переменной, вы можете иметь проблемы с потоковой безопасностью.
Согласитесь с другими ответами - просто запиской.
Если бы был случай, когда StringBuffer использовался несколькими потоками, это, вероятно, полностью сломанный вариант использования, потому что это означало бы, что одна строка строится в квази-случайном порядке, поэтому не имеет смысла сделать поток StringBuffer безопасным.
Я не уверен, нужен ли этот код, потому что Java автоматически выбирает StringBuilder. Если у вас нет проблемы с производительностью, перейдите к + b.
В случае потребности в производительности попробуйте следующее:
return new StringBuilder(
a.length() + b.length()).append(a).append(b).toString();
Он правильно сортирует буфер и не позволяет виртуальной машине изменять размер и создавать мусор, чтобы собрать по пути.