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

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

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

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

Ответы

Ответ 1

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

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

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

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

Проверьте это:

Ответ 2

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

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

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

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

Ответ 3

Использование 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.

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

Это поможет вам, ребята, 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   -> 

Ответ 7

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

Ответ 8

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