Разница между StringBuilder и StringBuffer


Ответы:


1667

StringBufferсинхронизируется, StringBuilderнет.


239
и StringBuilder предназначен для замены StringBuffer, где синхронизация не требуется
Джоэль

95
и синхронизация практически никогда не требуется. Если кто-то хочет синхронизироваться с StringBuilder, он может просто окружить весь блок кода синхронизированным (sb) {} в экземпляре
locka

23
@locka Я бы сказал, что StringBuffer никогда не является хорошей идеей (если у вас нет API, который требует этого) vanillajava.blogspot.de/2013/04/…
Питер Лоури,

8
Единственное место, которое я вижу для StringBuffer, это консоль, похожая на вывод, и различные утилиты ведения журнала: многие потоки могут выводить конфликтующие данные. Поскольку вы не хотите, чтобы 2 выходных данных были перепутаны ... но обычно синхронизация на уровне StringBuffer является слишком низким уровнем, вам нужно синхронизировать данные на уровне приложения, такого как levelm, поэтому ответ locka является лучшим, а StringBuffer следует считать устаревшим. Это сэкономило бы время проверки кода с новичками.
Реми Морин

20
Хорошая мнемоника для тех, кто смешивает эти два - BuFFer был First, старше и, следовательно, синхронизировал реализацию. Более новый класс Builder использует шаблон Builder и является асинхронным.
Datageek

728

StringBuilderбыстрее, чем StringBufferпотому что это не так synchronized.

Вот простой тест производительности:

public class Main {
    public static void main(String[] args) {
        int N = 77777777;
        long t;

        {
            StringBuffer sb = new StringBuffer();
            t = System.currentTimeMillis();
            for (int i = N; i --> 0 ;) {
                sb.append("");
            }
            System.out.println(System.currentTimeMillis() - t);
        }

        {
            StringBuilder sb = new StringBuilder();
            t = System.currentTimeMillis();
            for (int i = N; i > 0 ; i--) {
                sb.append("");
            }
            System.out.println(System.currentTimeMillis() - t);
        }
    }
}

Тестовый прогон дает номера 2241 msдля StringBufferпротив 753 msдля StringBuilder.


10
Я изменил строковый литерал на нечто большее: «быстрая коричневая лиса» и получил более интересные результаты. В основном они примерно такие же быстрые. У меня фактически закончилась память, поэтому мне пришлось удалить несколько семерок. Объяснение: синхронизация оптимизирована с помощью горячей точки. По сути, вы просто измеряете время, которое требуется горячей точке для этого (и, возможно, еще несколько оптимизаций).
Жилль ван Гурп

7
Вы должны разогреться раньше. Этот тест несправедлив по отношению к StringBuffer. Кроме того, было бы хорошо, если бы он действительно что-то добавил. На самом деле я перевернул тест, добавил случайную строку и получил противоположный тест. Говорится, что нельзя доверять простым ориентирам. Наоборот показывает StringBuffer быстрее. 5164 для StringBuilder против 3699 для StringBuffer hastebin.com/piwicifami.avrasm
ммм

76
Это первый раз, когда я вижу --> 0в цикле. Мне потребовалось время, чтобы понять, что это значит. Это то, что на самом деле используется на практике вместо обычного ...; i > 0; i--синтаксиса?
Раймунд Кремер

19
Это i -->действительно раздражает синтаксис ... Сначала я подумал, что это стрелка из-за комментариев об искусстве ASCII.
Самер Пури

14
Другие заключают с другими результатами: alblue.bandlem.com/2016/04/jmh-stringbuffer-stringbuilder.html . Тесты действительно должны быть сделаны с JMH, а не с простым. main()Ваш тест несправедлив. Там нет разминки.
Лукас Эдер

249

В принципе, StringBufferметоды синхронизированы, пока StringBuilderнет.

Операции "почти" одинаковы, но использование синхронизированных методов в одном потоке является излишним.

Это довольно много об этом.

Цитата из StringBuilder API :

Этот класс [StringBuilder] предоставляет API-интерфейс, совместимый с StringBuffer, но без гарантии синхронизации . Этот класс предназначен для использования в качестве замены для StringBuffer в тех местах, где строковый буфер использовался одним потоком (как это обычно бывает). Там, где это возможно, рекомендуется использовать этот класс вместо StringBuffer, так как он будет быстрее в большинстве реализаций.

Так что это было сделано, чтобы заменить его.

То же самое случилось Vectorи с ArrayList.


1
Также с Hashtableи HashMap.
шмосел

177

Но нужно ли получить четкую разницу с помощью примера?

StringBuffer или StringBuilder

Просто используйте, StringBuilderесли вы действительно не пытаетесь разделить буфер между потоками. StringBuilderявляется несинхронизированным (менее затратным = более эффективным) младшим братом исходного синхронизированного StringBufferкласса.

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

StringBuilderпришел позже. Большинство использований StringBufferбыли однопоточными и без необходимости платили за синхронизацию.

Так StringBuilderкак это замена для StringBufferсинхронизации без синхронизации, между примерами не будет различий.

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


14
Первый хороший ответ !! Дело в том, «если вы не разделяете буфер между потоками»
AlexWien

1
очень подробный ответ!
Рауль

81

Сначала давайте увидим сходство : и StringBuilder, и StringBuffer являются изменяемыми. Это означает, что вы можете изменить их содержимое, находясь в одном месте.

Отличия : StringBuffer изменчив и синхронизирован. Где, поскольку StringBuilder является изменяемым, но не синхронизируется по умолчанию.

Значение "синхронизированный" (синхронизация) : когда какая-либо вещь синхронизируется, несколько потоков могут получить к ней доступ и изменить ее без каких-либо проблем или побочных эффектов. StringBuffer синхронизирован, так что вы можете использовать его с несколькими потоками без каких-либо проблем.

Какой использовать когда? StringBuilder: когда вам нужна строка, которую можно изменить, и только один поток обращается к ней и изменяет ее. StringBuffer: когда вам нужна строка, которую можно изменить, и несколько потоков обращаются к ней и изменяют ее.

Примечание : не используйте StringBuffer без необходимости, т. Е. Не используйте его, если только один поток модифицирует и обращается к нему, потому что он имеет много кодов блокировки и разблокировки для синхронизации, которые излишне отнимают процессорное время. Не используйте замки, если это не требуется.


2
Просто хочу отметить, что вызовы метода INDIVIDUAL в StringBuffer являются поточно-ориентированными. Но если у вас несколько строк кода, используйте синхронизированный блок кода, чтобы гарантировать безопасность потоков, с некоторой блокировкой / монитором (как обычно ...). По сути, не просто предполагайте, что использование многопоточной библиотеки сразу гарантирует поточную безопасность в ВАШЕЙ программе!
Кевин Ли

57

В одиночных потоках StringBuffer не намного медленнее, чем StringBuilder , благодаря оптимизации JVM. А в многопоточности вы не можете безопасно использовать StringBuilder.

Вот мой тест (не тест, просто тест):

public static void main(String[] args) {

    String withString ="";
    long t0 = System.currentTimeMillis();
    for (int i = 0 ; i < 100000; i++){
        withString+="some string";
    }
    System.out.println("strings:" + (System.currentTimeMillis() - t0));

    t0 = System.currentTimeMillis();
    StringBuffer buf = new StringBuffer();
    for (int i = 0 ; i < 100000; i++){
        buf.append("some string");
    }
    System.out.println("Buffers : "+(System.currentTimeMillis() - t0));

    t0 = System.currentTimeMillis();
    StringBuilder building = new StringBuilder();
    for (int i = 0 ; i < 100000; i++){
        building.append("some string");
    }
    System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}

Результатов:
строк: 319740 Буферов
: 23
Строителей: 7!

Таким образом, Builders быстрее, чем Buffers, и WAY быстрее, чем конкатенация строк. Теперь давайте используем Executor для нескольких потоков:

public class StringsPerf {

    public static void main(String[] args) {

        ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
        //With Buffer
        StringBuffer buffer = new StringBuffer();
        for (int i = 0 ; i < 10; i++){
            executorService.execute(new AppendableRunnable(buffer));
        }
        shutdownAndAwaitTermination(executorService);
        System.out.println(" Thread Buffer : "+ AppendableRunnable.time);

        //With Builder
        AppendableRunnable.time = 0;
        executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
        StringBuilder builder = new StringBuilder();
        for (int i = 0 ; i < 10; i++){
            executorService.execute(new AppendableRunnable(builder));
        }
        shutdownAndAwaitTermination(executorService);
        System.out.println(" Thread Builder: "+ AppendableRunnable.time);

    }

   static void shutdownAndAwaitTermination(ExecutorService pool) {
        pool.shutdown(); // code reduced from Official Javadoc for Executors
        try {
            if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
                pool.shutdownNow();
                if (!pool.awaitTermination(60, TimeUnit.SECONDS))
                    System.err.println("Pool did not terminate");
            }
        } catch (Exception e) {}
    }
}

class AppendableRunnable<T extends Appendable> implements Runnable {

    static long time = 0;
    T appendable;
    public AppendableRunnable(T appendable){
        this.appendable = appendable;
    }

    @Override
    public void run(){
        long t0 = System.currentTimeMillis();
        for (int j = 0 ; j < 10000 ; j++){
            try {
                appendable.append("some string");
            } catch (IOException e) {}
        }
        time+=(System.currentTimeMillis() - t0);
    }
}

Теперь StringBuffers занимают 157 мс на 100000 операций добавления. Это не тот же тест, но по сравнению с предыдущими 37 мс, вы можете смело предположить, что добавления StringBuffers медленнее при использовании многопоточности . Причина в том, что JIT / горячая точка / компилятор / что-то оптимизирует, когда обнаруживает, что нет необходимости проверять блокировки.

Но с StringBuilder у вас есть java.lang.ArrayIndexOutOfBoundsException , потому что параллельный поток пытается добавить что-то, где он не должен.

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


5
Вы забыли сделать "t0 = System.currentTimeMillis ();" перед выполнением теста StringBuilder. Таким образом, показатель, отображаемый для StringBuilder, - это фактически время, необходимое для запуска теста stringbuffer AND stringbuilder. Добавьте эту строку, и вы увидите, что StringBuilder работает быстрее примерно в два раза.
Гена Бацян

Обратите внимание, что withString+="some string"+i+" ; ";это не эквивалентно двум другим циклам и, следовательно, не является справедливым сравнением.
Дейв Джарвис

Точно, исправлено. Строки мысли все еще очень медленные.
Николас Зозол

Можете ли вы объяснить больше, почему повышается ArrayIndexOutOfBoundsException для StringBuilder
Алиреза Фаттахи,

Вы должны использовать JMH для тестов. Ваш эталон действительно неточный.
Лукас Эдер

42

StringBuilder был представлен в Java 1.5, поэтому он не будет работать с более ранними версиями JVM.

Из Javadocs :

Класс StringBuilder предоставляет API-интерфейс, совместимый с StringBuffer, но без гарантии синхронизации. Этот класс предназначен для использования в качестве замены для StringBuffer в тех местах, где строковый буфер использовался одним потоком (как это обычно бывает). Там, где это возможно, рекомендуется использовать этот класс вместо StringBuffer, так как он будет быстрее в большинстве реализаций.


13
1.4 находится в конце срока службы, так что вряд ли стоит беспокоиться о pre-1.5.
Том Хотин - tackline

@ tomHawtin-tackline не обязательно - есть версии для предприятий до версии 1.4, которые большинство из нас использует ежедневно. Также BlackBerry Java основан на 1.4, и это все еще очень актуально.
Ричард Ле Мезурье

И CDC и CLDC не имеют StringBuilder.
Джин Квон

37

Довольно хороший вопрос

Вот различия, я заметил:

StringBuffer: -

StringBuffer is  synchronized
StringBuffer is  thread-safe
StringBuffer is  slow (try to write a sample program and execute it, it will take more time than StringBuilder)

StringBuilder: -

 StringBuilder is not synchronized 
 StringBuilder is not thread-safe
 StringBuilder performance is better than StringBuffer.

Общая вещь: -

Оба имеют одинаковые методы с одинаковыми сигнатурами. Оба изменчивы.


23

StringBuffer

  • Синхронизированный следовательно потокобезопасный
  • Поток безопасен, следовательно, медленный

StringBuilder

  • Введено в Java 5.0
  • Асинхронный, следовательно, быстрый и эффективный
  • Пользователь явно должен синхронизировать его, если он хочет
  • Вы можете заменить его StringBufferбез каких-либо других изменений

ПРИМЕЧАНИЕ. Только отдельные операции являются поточно-ориентированными, а несколько операций - нет. например , если вы звоните в appendдва раза, или appendи toStringне не безопасно.
Питер Лори

22

StringBuilder не является потокобезопасным. Строковый буфер есть. Больше информации здесь .

РЕДАКТИРОВАТЬ: Что касается производительности, после запуска горячей точки , StringBuilder является победителем. Однако для небольших итераций разница в производительности незначительна.


21

StringBuilderи StringBufferпочти одинаковы. Разница в том, что StringBufferсинхронизируется и StringBuilderнет. Хотя StringBuilderбыстрее StringBuffer, разница в производительности очень мала. StringBuilderявляется заменой СОЛНЦА StringBuffer. Он просто избегает синхронизации со всеми общедоступными методами. Вместо этого их функциональность одинакова.

Пример хорошего использования:

Если ваш текст собирается измениться и используется несколькими потоками, то лучше использовать StringBuffer. Если ваш текст собирается измениться, но используется одним потоком, используйте StringBuilder.


19

StringBuffer

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

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

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

Значение StringBuffer может быть изменено, это означает, что оно может быть присвоено новому значению. В настоящее время это наиболее распространенный вопрос интервью, различия между вышеуказанными классами. Строковый буфер может быть преобразован в строку с помощью метода toString ().

StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .

demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer

StringBuilder

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

StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified

demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder

введите описание изображения здесь

Ресурс: String Vs StringBuffer Vs StringBuilder


StringBuilder является неизменным, а тип String изменяемым
Brinda Rathod

Я не согласен с тем, что Strings и StringBuilders «быстрые», а StringBuffers «очень медленные». Смотрите ответы выше.
FireCubez

17

String является неизменным.

StringBuffer является изменчивым и синхронизированным.

StringBuilder также изменчив, но не синхронизирован.


Кроме того, StringBuffer блокирует потоки для доступа к этим потокобезопасным данным, поэтому работа идет медленно. StringBuilder не блокирует поток и работает в многопоточном режиме, поэтому работает быстро. String - когда вам не нужно объединять строку, это хороший способ, но когда вам это нужно, используйте StringBuilder ->, потому что String создает каждый раз новый объект в куче, а StringBuilder возвращает один и тот же объект ...
Musa

11

Javadoc объясняет разницу:

Этот класс предоставляет API-интерфейс, совместимый с StringBuffer, но без гарантии синхронизации. Этот класс предназначен для использования в качестве замены для StringBuffer в тех местах, где строковый буфер использовался одним потоком (как это обычно бывает). Там, где это возможно, рекомендуется использовать этот класс вместо StringBuffer, так как он будет быстрее в большинстве реализаций.


10

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

Прочитайте учебник для более подробной информации.


6

Простая программа, иллюстрирующая разницу между StringBuffer и StringBuilder:

/**
 * Run this program a couple of times. We see that the StringBuilder does not
 * give us reliable results because its methods are not thread-safe as compared
 * to StringBuffer.
 * 
 * For example, the single append in StringBuffer is thread-safe, i.e.
 * only one thread can call append() at any time and would finish writing
 * back to memory one at a time. In contrast, the append() in the StringBuilder 
 * class can be called concurrently by many threads, so the final size of the 
 * StringBuilder is sometimes less than expected.
 * 
 */
public class StringBufferVSStringBuilder {

    public static void main(String[] args) throws InterruptedException {

        int n = 10; 

        //*************************String Builder Test*******************************//
        StringBuilder sb = new StringBuilder();
        StringBuilderTest[] builderThreads = new StringBuilderTest[n];
        for (int i = 0; i < n; i++) {
            builderThreads[i] = new StringBuilderTest(sb);
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            builderThreads[i].join();
        }
        System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());

        //*************************String Buffer Test*******************************//

        StringBuffer sb2 = new StringBuffer();
        StringBufferTest[] bufferThreads = new StringBufferTest[n];
        for (int i = 0; i < n; i++) {
            bufferThreads[i] = new StringBufferTest(sb2);
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].start();
        }
        for (int i = 0; i < n; i++) {
            bufferThreads[i].join();
        }
        System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());

    }

}

// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {

    StringBuilder sb;

    public StringBuilderTest (StringBuilder sb) {
        this.sb = sb;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb.append("A");
        }

    }
}


//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {

    StringBuffer sb2;

    public StringBufferTest (StringBuffer sb2) {
        this.sb2 = sb2;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            sb2.append("A");
        }

    }
}

4

StringBuffer используется для хранения строк символов, которые будут изменены (объекты String не могут быть изменены). Он автоматически расширяется по мере необходимости. Связанные классы: String, CharSequence.

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


4
Однопоточные программы - не самый распространенный случай в Java, но StringBuilderобычно они локальны для метода, где они видны только одному потоку.
finnw


4

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

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


4

StringBuffer:

  • Многопотоковый
  • синхронизированный
  • Медленнее, чем StringBuilder

StringBuilder

  • Однозаходные
  • Не-Синхронное
  • Быстрее, чем когда-либо String

2
Точнее, String c = a + bэквивалентно String c = new StringBuilder().append(a).append(b).toString(), поэтому не быстрее. Это только то , что вы создаете новую для каждой строки передачи имущества, в то время как вы можете иметь только один ( String d = a + b; d = d + c;это в String d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();то время как StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString();бы сохранить один StringBuilder при создании экземпляра).
Чоп

4

String-Builder :

int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.

Строка-буфер

StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);  

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


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

4

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


3
@Mark true, но в большинстве случаев StringBu(ff|ild)erэто локальная переменная, используемая только одним потоком.
Габузо

1
@MarkMcKenna: даже в многопоточных приложениях часто приходится либо использовать внешнюю блокировку, либо выполнять дополнительную работу, чтобы ее избежать. Например, если два потока хотят добавить запись, содержащую несколько строк, в построитель строк, им придется объединить данные для добавления, а затем добавить их как единое целое, даже если бы это было быстрее - при отсутствии проблем с потоками - просто выполнить последовательность отдельных операций добавления.
суперкат

3

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


3

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

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


3

A Stringявляется неизменным объектом, что означает, что значение не может быть изменено, тогда какStringBuffer оно изменчиво.

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


3
просто потому, что StringBuffer имеет синхронизированный код, не обязательно означает, что StringBuffer является потокобезопасным. Рассмотрим следующий пример: StringBuffer testingBuffer = "stackoverflow"; Теперь Thread-1 пытается добавить «1» к testingBuffer, а Thread-2 пытается добавить «2» к testingBuffer. Теперь, даже несмотря на то, что метод append () синхронизирован, вы не можете быть уверены, будет ли значением testingBuffer быть «stackoverflow12» или «stackoverflow21». На самом деле, Oracle рекомендует использовать stringbuilder поверх stringbuffer. Я надеюсь, что это помогло :)
Биман Трипати

2

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


4
StringBuffer безопасен только для потоков, если вы выполняете только одну операцию над ним. Я бы не рекомендовал использовать его в нескольких потоках, потому что это очень трудно понять правильно.
Питер Лори

@PeterLawrey что ты имеешь в виду? :-)
Тамад Ланг,

1
@ b16db0 Я имею в виду, что большинство применений StringBuffer не являются поточно-ориентированными, так как они выполняют многочисленные вызовы без внешней синхронизации, что делает класс довольно бессмысленным.
Питер Лори

@PeterLawrey ах, как будто StringBuffer все еще нуждается в синхронизированной среде.
Тамад Ланг,

2

Проверьте внутренние компоненты синхронизированного метода добавления StringBufferи несинхронизированного метода добавления StringBuilder.

StringBuffer :

public StringBuffer(String str) {
    super(str.length() + 16);
    append(str);
}

public synchronized StringBuffer append(Object obj) {
    super.append(String.valueOf(obj));
    return this;
}

public synchronized StringBuffer append(String str) {
    super.append(str);
    return this;
}

StringBuilder :

public StringBuilder(String str) {
    super(str.length() + 16);
    append(str);
}

public StringBuilder append(Object obj) {
    return append(String.valueOf(obj));
}

public StringBuilder append(String str) {
    super.append(str);
    return this;
}

Так как append is synchronized, StringBufferимеет снижение производительности по сравнению с StrinbBuilderмногопоточным сценарием. Пока вы не разделяете буфер между несколькими потоками, используйте его StringBuilder, что быстро из-за отсутствия synchronizedметодов добавления.


1

Вот результат тестирования производительности для String vs StringBuffer vs StringBuilder . Наконец, StringBuilder выиграл тест. Ниже приведен тестовый код и результат.

Код :

private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test

int loop = 100000;
long start = 0;

// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
  str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");

// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
  sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");

// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
  sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");

  }

Казни меня на идоне

Результат :

100000 итераций для добавления одного текста

String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms

10000 итераций для добавления одного текста

String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms

1
  • StringBuffer является поточно-ориентированным, но StringBuilder не является поточно-ориентированным.
  • StringBuilder работает быстрее, чем StringBuffer.
  • StringBuffer синхронизируется, тогда как StringBuilder не синхронизируется.

1

StringBuffer синхронизирован и потокобезопасен, StringBuilder не синхронизируется и работает быстрее.


Эта разница была дана во всех других ответах на этот вопрос. Не могли бы вы выделить что-то новое?
Нико
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.