Коли я повинен використовувати 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 не є безпечним для потоків.
— Martijn Verburg

2
@MartijnVerburg Щоправда, хоча це було зазначено в stackoverflow.com/questions/6775016/stringbuffer-is-obsolete/…, що існує дуже мало випадків використання, які вимагають декількох потоків використовувати один і той же екземпляр будівельника String.
— Меттью Флінн

4
@MartijnVerburg: слід також зазначити: якщо вам справді потрібна безпека ниток, то ймовірність цього StringBufferтеж недостатня! Це гарантує, що воно не гальмує, але положення, в якому ви додаєте, не може бути легко керуватися, якщо відразу декілька потоків отримують доступ до нього, тому потрібна буде інша зовнішня синхронізація.
— Йоахім Зауер

8

StringBuilder був доданий у точці (Java 1.5), щоб бути кращим і швидшим StringBuffer, і компілятор використовує його під кришкою для реалізації +оператора на Strings.

Це означає, що за допомогою StringBuilder ви не можете змусити свій код працювати на JVM старше, ніж коли було представлено клас. Це було б для нас проблемою, на деякий час. Якщо ви завжди запускаєте останню версію, вам не потрібно дбати.

Я б не пройшов процес оптимізації, який ви проходили, хоча з наступних причин.

  • Зовні тісні петлі перевага незначна. Якщо це явно не відображається як гаряча точка у профіле, я б не переймався.
  • Зміна коду може ввести помилки, і ви повинні ретельно перевірити свою заявку. Це може бути набагато дорожче, ніж життя з синхронізованим класом у не синхронізованій обстановці.

Я згоден з вами .. все ще не в змозі зрозуміти вашу думкуOutside tight loops the advantage is negligible...
— Satish Pandey

Механізм, який відсутній у StringBuilder, на відміну від StringBuffer, - це швидкість торгівлі для безпеки потоку. Таке покращення швидкості дуже мало, тому важливо лише, якщо це робиться багато разів - зазвичай це відбувається в невеликому циклі, який робиться багато разів.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.