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

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

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

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

8 ответов


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

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

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

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

зацени вот это :


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

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

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

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


использование 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 и log lines одновременно для класса, такого как Writer.


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

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

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


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

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


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

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   -> 

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


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