Когда я должен использовать StringBuilder или StringBuffer?

13

В производственном веб-приложении мои коллеги-программисты везде использовали StringBuffer. Сейчас я занимаюсь разработкой и исправлением приложений. После прочтения StringBuilder и StringBuffer я решил заменить весь код StringBuffer на StringBuilder, потому что нам не нужна безопасность потоков в наших компонентах данных.

Например: (В каждом бине данных я вижу использование StringBuffer)

@Override
public String toString() {
    StringBuffer sb = new StringBuffer();// replace it from StringBuilder
    sb.append(" ABCD : ").append(abcd);
    sb.append(", EFGH : ").append(efgh);
    sb.append(", IJKL : ").append(ijkl);
}

Мы создаем отдельные компоненты данных для каждой сессии / запроса. Сеанс используется одним пользователем, другой пользователь не может получить к нему доступ.

Должен ли я рассмотреть другие вопросы перед миграцией?

Если существует один поток (нет ожидающих потоков / новый поток не будет искать блокировку объекта), он работает одинаково с StringBuffer или StringBuilder. Я знаю, что в случае StringBuffer требуется время для блокировки объекта, но я хочу знать, есть ли между ними разница в производительности, кроме удержания / снятия блокировки объекта.

Сатиш Пандей
источник
9
Если вы используете sbв качестве локальной переменной, как в вашем примере, тогда безопасность потоков вообще не имеет значения. Даже если в метод одновременно войдет тысяча потоков, у каждого будет свой стек вызовов со своими локальными переменными. StringBuilders никогда не будут мешать друг другу.
fredoverflow
Мне всегда было интересно, кто хочет синхронизировать два потока по интерфейсу StringBuffer. Я никогда не видел такого кода, но я почти уверен, что это плохой дизайн с точки зрения многопоточности. Поскольку я думаю, что синхронизация потоков по StringBufferинтерфейсу - плохая идея, я думаю, что этот класс не должен существовать, и его всегда следует использовать StringBuilder. Как уже упоминалось, StringBufferсуществует по историческим причинам.
pasztorpisti

Ответы:

22

Единственная разница между ними заключается в синхронизации, используемой в StringBuffer. Затраты на синхронизацию не велики в общей схеме вещей, но они значительны по сравнению с методами StringBuilder, у которых их нет. JVM выполняет работу, которую иначе не пришлось бы выполнять, особенно с одним потоком и т. Д.

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

Мэтью Флинн
источник
Я добавлю к этому, что вам нужно помнить о безопасности наследуемых потоков. StringBuilder не является потокобезопасным.
Мартейн Вербург
2
@MartijnVerburg Правда, хотя в stackoverflow.com/questions/6775016/stringbuffer-is-obsolete/ было указано, что существует очень мало случаев, когда нескольким потокам требуется использовать один и тот же экземпляр String Builder.
Мэтью Флинн
4
@MartijnVerburg: также следует отметить: если вам действительно нужна безопасность потоков, скорее всего, этого StringBufferтоже недостаточно! Это гарантирует, что он не тормозит, но положение, в котором вы добавляете, не может легко контролироваться, если к нему обращаются сразу несколько потоков, поэтому потребуется другая внешняя синхронизация.
Иоахим Зауэр
8

StringBuilder был добавлен в точку (Java 1.5), чтобы стать лучше и быстрее StringBuffer, и компилятор использует его под капюшоном для реализации +оператора в строках.

Это означает, что с помощью StringBuilder вы не можете заставить свой код работать на JVM старше, чем когда был представлен класс. Это будет проблемой для нас, пока. Если вы всегда запускаете последнюю версию, вам не нужно заботиться.

Я бы не стал проходить процесс оптимизации, который вы проходите, хотя бы по следующим причинам.

  • Снаружи узкие петли преимущество незначительно. Если бы это явно не отображалось как точка доступа в профилировщике, я бы не стал беспокоиться.
  • Изменение кода может привести к ошибкам, и вы должны тщательно протестировать свое приложение. Это может быть намного дороже, чем жить с синхронизированным классом в несинхронизированной обстановке.
Фрэнк Шиарар
источник
Я согласен с вами .. все еще не в состоянии понять вашу точку зренияOutside tight loops the advantage is negligible...
Сатиш Пандей
Механизм, который отсутствует в StringBuilder, в отличие от StringBuffer, - это скорость торговли для обеспечения безопасности потоков. Это улучшение скорости очень мало, поэтому имеет значение, только если оно выполняется много раз - обычно это происходит в небольшом цикле, который выполняется много раз.