Зачем использовать StringBuilder? StringBuffer может работать с несколькими потоками, а также с одним потоком?

Предположим, в нашем приложении есть только один поток. а мы используем StringBuffer, тогда в чем проблема?

Я имею в виду, если StringBuffer может обрабатывать несколько потоков посредством синхронизации, в чем проблема при работе с одним потоком?

Зачем вместо этого использовать StringBuilder?


person MANISH PATHAK    schedule 30.05.2011    source источник


Ответы (8)


StringBuffers являются потокобезопасными, что означает, что у них есть синхронизированные методы для управления доступом, так что только один поток может одновременно получить доступ к синхронизированному коду объекта StringBuffer. Таким образом, объекты StringBuffer, как правило, безопасно использовать в многопоточной среде, где несколько потоков могут одновременно пытаться получить доступ к одному и тому же объекту StringBuffer.

StringBuilder's доступ не синхронизирован, поэтому он не является потокобезопасным. Без синхронизации производительность StringBuilder может быть лучше, чем StringBuffer. Таким образом, если вы работаете в однопоточной среде, использование StringBuilder вместо StringBuffer может привести к повышению производительности. Это также верно и для других ситуаций, таких как локальная переменная StringBuilder (т. Е. Переменная внутри метода), где только один поток будет обращаться к объекту StringBuilder.

Итак, предпочитайте StringBuilder, потому что,

  • Небольшой прирост производительности.
  • StringBuilder - это прямая замена 1: 1 для класса StringBuffer.
  • StringBuilder не синхронизируется по потокам и поэтому лучше работает в большинстве реализаций Java.

Проверь это :

person Saurabh Gokhale    schedule 30.05.2011
comment
Лучше сказать, что StringBuffer является потокобезопасным, но очень легко придумать сценарии, в которых два потока, конкурирующие за один и тот же буфер, вызывают условия гонки. Даже если вам необходимо совместно использовать строковый буфер между потоками, весьма вероятно, что вам потребуется применить к нему более высокий уровень управления, чем синхронизированные методы, которые он показывает. Поэтому я не могу придумать много причин для использования StringBuffer, если сторонняя библиотека не требует, чтобы вы использовали ее, или для устаревших / нишевых целей. - person locka; 28.03.2014
comment
StringBuilder - это не точная замена 1: 1 для StringBuffer. Например, метод appendReplacement для Matcher требует StringBuffer в качестве первого аргумента. - person Josh Broadhurst; 10.01.2018

StringBuilder должен быть (крошечным) немного быстрее, потому что он не синхронизирован (потокобезопасен).

Вы можете заметить разницу в действительно тяжелых приложениях.

Класс StringBuilder обычно следует использовать вместо этого, поскольку он поддерживает все те же операции, но работает быстрее, так как не выполняет синхронизацию.

http://download.oracle.com/javase/6/docs/api/java/lang/StringBuffer.html

person Bart Vangeneugden    schedule 30.05.2011
comment
@MANISH PATHAK - прочтите ответ - вопрос: Why use StringBuilder instead? - ответ: StringBuilder is supposed to be a (tiny) bit faster (первое предложение этого сообщения) - person user85421; 30.05.2011
comment
Чтобы уточнить: даже когда один поток использует объект, синхронизированные методы заставляют поток получать и освобождать монитор для каждого доступа. Это может замедлить работу программы. - person Jonathan; 30.05.2011

Использование StringBuffer в нескольких потоках почти бесполезно и в действительности почти никогда не происходит.

Рассмотрим следующие

Thread1: sb.append(key1).append("=").append(value1);
Thread2: sb.append(key2).append("=").append(value2);

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

key1=value1key2=value2
key1key2==value2value1
key2key1=value1=value2
key2=key1=value2value1

Этого можно избежать, синхронизируя всю строку за раз, но это лишает смысла использование StringBuffer вместо StringBuilder.

Даже если у вас есть правильно синхронизированное представление, это сложнее, чем просто создание локальной копии потока всей строки, например. StringBuilder и записывать строки в класс, например Writer.

person Peter Lawrey    schedule 30.05.2011

StringBuffer не является неправильным в однопоточном приложении. Он будет работать так же хорошо, как StringBuilder.

Единственное отличие состоит в небольших накладных расходах, добавляемых наличием всех синхронизированных методов, что не дает преимуществ в однопоточном приложении.

Я считаю, что основная причина появления StringBuilder заключается в том, что компилятор использует StringBuffer (а теперь StringBuilder) при компиляции кода, содержащего String конкатенацию: в этих случаях синхронизация выполняется никогда необходимо, и замена всех этих мест несинхронизированным StringBuilder может дать небольшое улучшение производительности.

person Joachim Sauer    schedule 30.05.2011

StringBuilder имеет лучшую производительность, потому что его методы не синхронизируются.

Так что, если вам не нужно создавать String одновременно (что в любом случае является довольно нетипичным сценарием), тогда нет необходимости «платить» за ненужные накладные расходы на синхронизацию.

person Andreas Dolk    schedule 30.05.2011
comment
Вы можете описать этот сценарий? - person MANISH PATHAK; 30.05.2011
comment
@Manish - нет, я не могу, потому что на самом деле я не могу представить сценарий, в котором мне пришлось бы выбрать StringBuffer вместо StringBuilder. - person Andreas Dolk; 30.05.2011
comment
Спасибо, Андреас ... Я получил это из сообщения выше. Спасибо всем - person MANISH PATHAK; 30.05.2011

Это поможет вам, ребята, Be Straight Builder быстрее, чем Buffer,

public class ConcatPerf {
        private static final int ITERATIONS = 100000;
        private static final int BUFFSIZE = 16;

        private void concatStrAdd() {
            System.out.print("concatStrAdd   -> ");
            long startTime = System.currentTimeMillis();
            String concat = new String("");
            for (int i = 0; i < ITERATIONS; i++) {
                concat += i % 10;
            }
            //System.out.println("Content: " + concat);
            long endTime = System.currentTimeMillis();
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        private void concatStrBuff() {
            System.out.print("concatStrBuff  -> ");
            long startTime = System.currentTimeMillis();
            StringBuffer concat = new StringBuffer(BUFFSIZE);
            for (int i = 0; i < ITERATIONS; i++) {
                concat.append(i % 10);
            }
            long endTime = System.currentTimeMillis();
            //System.out.println("Content: " + concat);
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        private void concatStrBuild() {
            System.out.print("concatStrBuild -> ");
            long startTime = System.currentTimeMillis();
            StringBuilder concat = new StringBuilder(BUFFSIZE);
            for (int i = 0; i < ITERATIONS; i++) {
                concat.append(i % 10);
            }
            long endTime = System.currentTimeMillis();
           // System.out.println("Content: " + concat);
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        public static void main(String[] args) {
            ConcatPerf st = new ConcatPerf();
            System.out.println("Iterations: " + ITERATIONS);
            System.out.println("Buffer    : " + BUFFSIZE);

            st.concatStrBuff();
            st.concatStrBuild();
            st.concatStrAdd();
        }
    }

Output  

    run:
    Iterations: 100000
    Buffer    : 16
    concatStrBuff  -> length: 100000 time: 11
    concatStrBuild -> length: 100000 time: 4
    concatStrAdd   -> 
person MyStack    schedule 17.02.2013

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

person Praveen    schedule 05.06.2013

Синхронизация объектов требует огромных затрат. Не рассматривайте программу как отдельную сущность; это не проблема, когда вы читаете концепции и применяете их в небольших программах, как вы упомянули в деталях вашего вопроса, проблемы возникают, когда мы хотим масштабировать систему. В этом случае ваша однопоточная программа может зависеть от нескольких других методов / программ / сущностей, поэтому синхронизированные объекты могут вызвать серьезную сложность программирования с точки зрения производительности. Поэтому, если вы уверены, что нет необходимости синхронизировать объект, вам следует использовать StringBuilder, поскольку это хорошая практика программирования. В конце мы хотим научиться программированию для создания масштабируемых высокопроизводительных систем, так что это то, что мы должны делать!

person Nikhil Arora    schedule 10.06.2017