Differenza tra StringBuilder e StringBuffer


1578

Qual è la differenza principale tra StringBuffere StringBuilder? Ci sono problemi di prestazioni quando si decide su uno di questi?

Risposte:


1667

StringBufferè sincronizzato, StringBuildernon lo è.


239
e StringBuilder è inteso come una sostituzione in sostituzione di StringBuffer in cui non è richiesta la sincronizzazione
Joel

95
e la sincronizzazione non è praticamente mai richiesta. Se qualcuno vuole sincronizzarsi su StringBuilder, può semplicemente circondare l'intero blocco di codice con un sincronizzato (sb) {}
sull'istanza

23
@locka Direi che StringBuffer non è mai una buona idea (a meno che tu non abbia un'API che lo richiede) vanillajava.blogspot.de/2013/04/…
Peter Lawrey

8
L'unico posto che vedo per StringBuffer è l'output come console e varie utilità di registrazione: molti thread potrebbero generare output in conflitto. Dal momento che non vuoi che 2 output vengano confusi ... ma di solito la sincronizzazione a livello StringBuffer è troppo bassa, ti consigliamo di sincronizzarti a un appender come levelm, quindi la risposta locka è la migliore e StringBuffer dovrebbe essere deprecato. Si risparmierebbe tempo di revisione del codice con i neofiti.
Remi Morin,

20
Buon mnemonico per coloro che mescolano questi due - BuFFer era l'implementazione Prima, più vecchia e quindi sincronizzata. La classe Builder più recente utilizza il modello Builder ed è asincrona.
Datageek,

728

StringBuilderè più veloce di StringBufferperché non lo è synchronized.

Ecco un semplice test di riferimento:

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);
        }
    }
}

Una corsa di prova fornisce i numeri di 2241 msfor StringBuffervs 753 msfor StringBuilder.


10
Ho cambiato la stringa letteralmente in qualcosa di più grande: "la rapida volpe marrone" e ho ottenuto risultati più interessanti. Fondamentalmente, sono più veloci. In realtà ho esaurito la memoria, quindi ho dovuto rimuovere alcuni sette. Spiegazione: la sincronizzazione è ottimizzata dall'hotspot. Fondamentalmente stai solo misurando il tempo impiegato dall'hotspot per farlo (e probabilmente qualche altra ottimizzazione).
Jilles van Gurp,

7
Devi riscaldarti prima. Questo test non è corretto per StringBuffer. Inoltre, sarebbe utile se aggiungesse effettivamente qualcosa. In realtà, ho lanciato il test, ho aggiunto una stringa casuale e ho ottenuto il test opposto. Va da sé che non ci si può fidare di semplici parametri di riferimento. Il contrario mostra StringBuffer è più veloce. 5164 per StringBuilder vs 3699 per StringBuffer hastebin.com/piwicifami.avrasm
mmm

75
Questa è la prima volta che vedo --> 0in loop. Mi ci è voluto un momento per capire cosa significa. È qualcosa che viene effettivamente utilizzato nella pratica invece della solita ...; i > 0; i--sintassi?
Raimund Krämer,

19
È i -->davvero fastidioso per la sintassi ... all'inizio pensavo che fosse una freccia a causa dei commenti sull'arte ASCII.
Sameer Puri,

14
Altri concludono con risultati diversi: alblue.bandlem.com/2016/04/jmh-stringbuffer-stringbuilder.html . I benchmark dovrebbero davvero essere fatti con JMH, non con un semplice main()Inoltre, il tuo benchmark non è giusto. Non c'è riscaldamento.
Lukas Eder,

249

Fondamentalmente, i StringBuffermetodi sono sincronizzati mentre StringBuildernon lo sono.

Le operazioni sono "quasi" uguali, ma l'utilizzo di metodi sincronizzati in un singolo thread è eccessivo.

È praticamente tutto.

Citazione dall'API StringBuilder :

Questa classe [StringBuilder] fornisce un'API compatibile con StringBuffer, ma senza alcuna garanzia di sincronizzazione . Questa classe è progettata per essere utilizzata come sostituto drop-in per StringBuffer in luoghi in cui il buffer di stringa veniva utilizzato da un singolo thread (come generalmente accade). Laddove possibile, si consiglia di utilizzare questa classe preferibilmente a StringBuffer poiché sarà più veloce nella maggior parte delle implementazioni.

Quindi è stato fatto per sostituirlo.

Lo stesso è successo con Vectore ArrayList.


1
Anche con Hashtablee HashMap.
shmosel,

177

Ma hai bisogno di ottenere la chiara differenza con l'aiuto di un esempio?

StringBuffer o StringBuilder

Basta usare a StringBuildermeno che non si stia davvero cercando di condividere un buffer tra i thread. StringBuilderè il fratello minore non sincronizzato (meno sovraccarico = più efficiente) della StringBufferclasse sincronizzata originale .

StringBufferè venuto per primo. Sun si preoccupava della correttezza in tutte le condizioni, quindi l'hanno sincronizzata per renderla thread-safe per ogni evenienza.

StringBuilderè venuto dopo. La maggior parte degli usi di StringBufferera a thread singolo e pagava inutilmente il costo della sincronizzazione.

Poiché StringBuilderè un rimpiazzo per StringBuffersenza la sincronizzazione, non ci sarebbero differenze tra gli esempi.

Se si sta tentando di condivisione tra i thread, è possibile utilizzare StringBuffer, ma considerare se la sincronizzazione di livello superiore è necessario, ad esempio, forse invece di usare StringBuffer, si dovrebbe sincronizzare i metodi che utilizzano lo StringBuilder.


14
La prima buona risposta !! Il punto è "a meno che tu non stia condividendo un buffer tra thread"
AlexWien

1
risposta molto dettagliata!
Raúl,

81

Per prima cosa vediamo le somiglianze : Sia StringBuilder che StringBuffer sono mutabili. Ciò significa che puoi modificarne il contenuto, con nella stessa posizione.

Differenze : StringBuffer è anche mutabile e sincronizzato. Dove come StringBuilder è modificabile ma non sincronizzato per impostazione predefinita.

Significato della sincronizzazione (sincronizzazione) : quando una cosa è sincronizzata, è possibile accedere a più thread e modificarla senza alcun problema o effetto collaterale. StringBuffer è sincronizzato, quindi puoi usarlo con più thread senza alcun problema.

Quale usare quando? StringBuilder: quando hai bisogno di una stringa, che può essere modificabile, e solo un thread la sta accedendo e modificando. StringBuffer: quando hai bisogno di una stringa, che può essere modificabile, e più thread accedono e la modificano.

Nota : non utilizzare StringBuffer inutilmente, ovvero non utilizzarlo se un solo thread lo sta modificando e accedendo perché ha un sacco di codice di blocco e sblocco per la sincronizzazione che impiegherà inutilmente tempo della CPU. Non utilizzare i blocchi a meno che non sia necessario.


2
Voglio solo ricordare che le chiamate al metodo INDIVIDUAL di StringBuffer sono thread-safe. Ma se hai più righe di codice, usa un blocco di codice sincronizzato per garantire la sicurezza dei thread, con qualche blocco / monitoraggio (come al solito ...). Fondamentalmente, non dare per scontato che l'uso di una libreria thread-safe garantisca immediatamente la sicurezza thread nel TUO programma!
Kevin Lee

57

Nei thread singoli, StringBuffer non è significativamente più lento di StringBuilder , grazie alle ottimizzazioni JVM. E nel multithreading, non è possibile utilizzare in sicurezza StringBuilder.

Ecco il mio test (non un benchmark, solo un test):

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));
}

Risultati:
stringhe: 319740
Buffer: 23
Costruttore: 7!

Quindi i Builders sono più veloci dei Buffer e WAY più veloci della concatenazione delle stringhe. Ora usiamo un Executor per più thread:

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);
    }
}

Ora StringBuffers impiega 157 ms per 100000 accodamenti. Non è lo stesso test, ma rispetto ai precedenti 37 ms, puoi tranquillamente supporre che le aggiunte di StringBuffers siano più lente con l'uso del multithreading . La ragione è che il JIT / hotspot / compilatore / qualcosa rende ottimizzazioni quando rileva che non v'è alcuna necessità di controllare le serrature.

Ma con StringBuilder, hai java.lang.ArrayIndexOutOfBoundsException , perché un thread simultaneo tenta di aggiungere qualcosa dove non dovrebbe.

La conclusione è che non devi inseguire StringBuffers. E dove hai i fili, pensa a cosa stanno facendo, prima di provare a guadagnare qualche nanosecondo.


5
Hai dimenticato di fare "t0 = System.currentTimeMillis ();" prima di eseguire il test StringBuilder. Quindi la figura visualizzata per StringBuilder è in realtà il tempo impiegato per eseguire il test stringbuffer E stringbuilder. Aggiungi questa riga e vedrai che StringBuilder È più veloce di DUE VOLTE.
Gena Batsyan,

Si noti che withString+="some string"+i+" ; ";non è equivalente agli altri due loop e non è quindi un confronto equo.
Dave Jarvis,

Esatto, corretto. Le stringhe di pensiero sono ancora molto lente.
Nicolas Zozol,

Puoi spiegare di più perché ArrayIndexOutOfBoundsException rilancia per StringBuilder
Alireza Fattahi il

È necessario utilizzare JMH per i benchmark. Il tuo benchmark è davvero impreciso.
Lukas Eder,

42

StringBuilder è stato introdotto in Java 1.5, quindi non funzionerà con le JVM precedenti.

Dai Javadocs :

La classe StringBuilder fornisce un'API compatibile con StringBuffer, ma senza garanzia di sincronizzazione. Questa classe è progettata per essere utilizzata come sostituto drop-in per StringBuffer in luoghi in cui il buffer di stringa veniva utilizzato da un singolo thread (come generalmente accade). Laddove possibile, si consiglia di utilizzare questa classe preferibilmente a StringBuffer poiché sarà più veloce nella maggior parte delle implementazioni.


13
1.4 è alla fine della sua vita utile, quindi non sembra quasi preoccuparsi della pre-1.5.
Tom Hawtin - tackline il

@ tomHawtin-tackline non necessariamente - ci sono prodotti aziendali disponibili sul pre 1.4 che la maggior parte di noi usa quotidianamente. Anche BlackBerry Java si basa su 1.4 ed è ancora molto attuale.
Richard Le Mesurier,

E CDC e CLDC non hanno StringBuilder.
Jin Kwon,

37

Domanda abbastanza buona

Ecco le differenze, ho notato:

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.

Cosa comune: -

Entrambi hanno gli stessi metodi con le stesse firme. Entrambi sono mutabili.


23

StringBuffer

  • Sincronizzato quindi thread-safe
  • Discussione sicura quindi lenta

StringBuilder

  • Introdotto in Java 5.0
  • Asincrono quindi veloce ed efficiente
  • L'utente deve esplicitamente sincronizzarlo, se lo desidera
  • Puoi sostituirlo con StringBuffersenza altre modifiche

NOTA: solo le singole operazioni sono thread-safe, non lo sono più operazioni. ad esempio, se si chiama appenddue volte, o appende toStringnon non è sicuro.
Peter Lawrey,

22

StringBuilder non è thread-safe. String Buffer è. Maggiori informazioni qui .

EDIT: Per quanto riguarda le prestazioni, dopo l' attivazione dell'hotspot , StringBuilder è il vincitore. Tuttavia, per piccole iterazioni, la differenza di prestazioni è trascurabile.


21

StringBuildere StringBuffersono quasi gli stessi. La differenza è che StringBufferè sincronizzato e StringBuildernon lo è. Sebbene, StringBuildersia più veloce di StringBuffer, la differenza nelle prestazioni è molto piccola. StringBuilderè un sostituto di SUN di StringBuffer. Evita solo la sincronizzazione da tutti i metodi pubblici. Invece, la loro funzionalità è la stessa.

Esempio di buon utilizzo:

Se il testo cambierà e verrà utilizzato da più thread, è meglio utilizzarlo StringBuffer. Se il testo cambierà ma viene utilizzato da un singolo thread, utilizzare StringBuilder.


19

StringBuffer

StringBuffer è mutabile significa che è possibile modificare il valore dell'oggetto. L'oggetto creato tramite StringBuffer è archiviato nell'heap. StringBuffer ha gli stessi metodi di StringBuilder, ma ogni metodo in StringBuffer è sincronizzato, ovvero StringBuffer è thread-safe.

per questo motivo non consente a due thread di accedere contemporaneamente allo stesso metodo. È possibile accedere a ciascun metodo da un thread alla volta.

Ma essere thread-safe ha anche degli svantaggi in quanto le prestazioni di StringBuffer colpiscono grazie alla proprietà thread-safe. Pertanto StringBuilder è più veloce di StringBuffer quando chiama gli stessi metodi di ogni classe.

Il valore StringBuffer può essere modificato, significa che può essere assegnato al nuovo valore. Oggi è una domanda di intervista più comune, le differenze tra le classi di cui sopra. String Buffer può essere convertito nella stringa utilizzando il metodo 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 è uguale a StringBuffer, ovvero memorizza l'oggetto nell'heap e può anche essere modificato. La principale differenza tra StringBuffer e StringBuilder è che StringBuilder non è anche sicuro per i thread. StringBuilder è veloce in quanto non è thread-safe.

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

inserisci qui la descrizione dell'immagine

Risorsa: String Vs StringBuffer Vs StringBuilder


StringBuilder è immutabile e il tipo String è mutabile
Brinda Rathod,

Non sarei d'accordo sul fatto che Strings e StringBuilders siano "veloci" e StringBuffer siano "molto lenti". Vedi le risposte sopra.
FireCubez,

17

String è un immutabile.

StringBuffer è mutabile e sincronizzato.

StringBuilder è anche mutabile ma non è sincronizzato.


Inoltre StringBuffer blocca i thread per accedere ai dati sicuri di questo thread, pertanto l'operazione procede lentamente. StringBuilder non blocca il thread e viene eseguito in modalità multithreading, ecco perché è veloce. String: quando non è necessario concatenare la stringa, questo è un buon metodo, ma quando è necessario, utilizzare StringBuilder -> perché String crea ogni volta un nuovo oggetto nell'heap, ma StringBuilder restituisce lo stesso oggetto ...
Musa,

11

Il javadoc spiega la differenza:

Questa classe fornisce un'API compatibile con StringBuffer, ma senza alcuna garanzia di sincronizzazione. Questa classe è progettata per essere utilizzata come sostituto drop-in per StringBuffer in luoghi in cui il buffer di stringa veniva utilizzato da un singolo thread (come generalmente accade). Laddove possibile, si consiglia di utilizzare questa classe preferibilmente a StringBuffer poiché sarà più veloce nella maggior parte delle implementazioni.


10

StringBuilder(introdotto in Java 5) è identico a StringBuffer, tranne che i suoi metodi non sono sincronizzati. Ciò significa che ha prestazioni migliori rispetto a quest'ultimo, ma lo svantaggio è che non è thread-safe.

Leggi il tutorial per maggiori dettagli.


6

Un semplice programma che illustra la differenza tra StringBuffer e 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 viene utilizzato per memorizzare stringhe di caratteri che verranno modificate (gli oggetti String non possono essere modificati). Si espande automaticamente secondo necessità. Classi correlate: String, CharSequence.

StringBuilder è stato aggiunto in Java 5. È identico sotto tutti gli aspetti a StringBuffer, tranne per il fatto che non è sincronizzato, il che significa che se più thread accedono ad esso contemporaneamente, potrebbero esserci problemi. Per i programmi a thread singolo, il caso più comune, evitando l'overhead della sincronizzazione rende StringBuilder molto più veloce.


4
I programmi a thread singolo non sono il caso più comune in Java, ma di StringBuildersolito sono locali a un metodo, dove sono visibili a un solo thread.
finnw

4

StringBufferè sincronizzato, ma StringBuildernon lo è. Di conseguenza, StringBuilderè più veloce di StringBuffer.


4

StringBuffer è modificabile. Può cambiare in termini di lunghezza e contenuto. StringBuffer sono thread-safe, nel senso che hanno metodi sincronizzati per controllare l'accesso in modo che solo un thread possa accedere al codice sincronizzato di un oggetto StringBuffer alla volta. Pertanto, gli oggetti StringBuffer sono generalmente sicuri da usare in un ambiente multi-thread in cui più thread potrebbero tentare di accedere allo stesso oggetto StringBuffer contemporaneamente.

StringBuilder La classe StringBuilder è molto simile a StringBuffer, tranne per il fatto che il suo accesso non è sincronizzato, quindi non è thread-safe. Non essendo sincronizzato, le prestazioni di StringBuilder possono essere migliori di StringBuffer. Pertanto, se si lavora in un ambiente a thread singolo, l'utilizzo di StringBuilder anziché StringBuffer può comportare un aumento delle prestazioni. Ciò vale anche per altre situazioni come una variabile locale StringBuilder (ovvero una variabile all'interno di un metodo) in cui solo un thread accederà a un oggetto StringBuilder.


4

StringBuffer:

  • Multi thread
  • sincronizzato
  • Lento di StringBuilder

StringBuilder

  • Singolo-Thread
  • Non-sincronizzato
  • Corda più veloce che mai

2
Più precisamente, String c = a + bequivale a String c = new StringBuilder().append(a).append(b).toString(), quindi non è più veloce. È solo che ne crei uno nuovo per ogni assegnazione di stringa, mentre potresti averne solo una ( String d = a + b; d = d + c;è il String d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();momento in cui StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString();salverebbe un'istanza di StringBuilder).
Taglia il

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.

String-Buffer

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

Si consiglia di utilizzare StringBuilder quando possibile perché è più veloce di StringBuffer. Tuttavia, se è necessaria la sicurezza del thread, l'opzione migliore è oggetti StringBuffer.


Se è necessaria la sicurezza del thread, l'opzione migliore è utilizzare StringBuilder poiché StringBuffer è thread-safe solo per le singole operazioni. Per più operazioni, è necessario il blocco esplicito.
Peter Lawrey,

4

Migliore utilizzo in StringBuilderquanto non sincronizzato e offre quindi prestazioni migliori. StringBuilderè un rimpiazzo sostitutivo del vecchio StringBuffer.


3
@Mark true ma il più delle volte StringBu(ff|ild)erè una variabile locale utilizzata solo da un singolo thread.
gabuzo,

1
@MarkMcKenna: anche in un'applicazione multi-thread, si dovrebbe spesso utilizzare il blocco esterno o fare un lavoro extra per evitarlo. Ad esempio, se due thread ciascuno desiderassero aggiungere un record contenente più stringhe a un stringbuilder, dovrebbero aggregare i dati da aggiungere e quindi aggiungerli come unità anche se sarebbe stato più veloce - assenza di problemi di threading - per eseguire semplicemente una sequenza di operazioni di aggiunta discrete.
supercat

3

Dato che StringBufferè sincronizzato, ha bisogno di qualche sforzo extra, quindi basato sulla perforazione, è un po 'più lento di StringBuilder.


3

Non ci sono differenze di base tra StringBuildere StringBuffer, esistono solo alcune differenze tra di loro. Nei StringBuffermetodi sono sincronizzati. Ciò significa che alla volta solo un thread può operare su di essi. Se è presente più di un thread, il secondo thread dovrà attendere il termine del primo e il terzo dovrà attendere il completamento del primo e del secondo e così via. Questo rende il processo molto lento e quindi le prestazioni nel caso diStringBuffer sono basse.

D'altra parte, StringBuildernon è sincronizzato. Ciò significa che contemporaneamente più thread possono operare sullo stesso StringBuilderoggetto contemporaneamente. Questo rende il processo molto veloce e quindi le prestazioni StringBuildersono elevate.


3

A Stringè un oggetto immutabile, il che significa che il valore non può essere modificato mentre StringBufferè mutabile.

Il StringBufferè sincronizzata quindi thread-safe che StringBuildernon e adatti sono solo a istanze thread singolo.


3
solo perché StringBuffer ha un codice sincronizzato, non significa necessariamente che StringBuffer sia thread-safe. Si consideri il seguente esempio: StringBuffer testingBuffer = "stackoverflow"; Ora Thread-1 sta provando ad aggiungere "1" a testingBuffer e Thread-2 sta provando ad aggiungere "2" a testingBuffer. Ora anche se il metodo append () è sincronizzato, non puoi essere sicuro che il valore di testingBuffer sarà "stackoverflow12" o "stackoverflow21". In realtà, Oracle consiglia di utilizzare Stringbuilder su StringBuffer. Spero che questo abbia aiutato :)
Biman Tripathy il

2

La differenza principale è che StringBufferè sincronizzata ma non lo StringBuilderè. Se è necessario utilizzare più di un thread, si consiglia StringBuffer, ma, secondo la velocità di esecuzione, StringBuilderè più veloce di StringBuffer, perché non è sincronizzato.


4
StringBuffer è thread-safe solo se si esegue una sola operazione su di esso. Non consiglierei di usarlo in più thread perché è molto difficile ottenere il giusto.
Peter Lawrey,

@PeterLawrey che vuoi dire? :-)
Tamad Lang,

1
@ b16db0 Voglio dire che la maggior parte degli usi di StringBuffer non sono sicuri per i thread in quanto effettuano più chiamate senza sincronizzazione esterna, rendendo la classe piuttosto inutile.
Peter Lawrey,

@PeterLawrey ah è come se StringBuffer avesse ancora bisogno di un ambiente sincronizzato.
Tamad Lang,

2

Controllare gli interni del metodo di aggiunta sincronizzato di StringBuffere il metodo di aggiunta non sincronizzato di 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;
}

Poiché append è synchronized, StringBufferha un sovraccarico di prestazioni rispetto allo StrinbBuilderscenario multi-threading. Finché non si condivide il buffer tra più thread, utilizzare StringBuilder, che è veloce a causa dell'assenza di synchronizedmetodi in append.


1

Ecco il risultato del test delle prestazioni per String vs StringBuffer vs StringBuilder . Alla fine, StringBuilder ha vinto il test. Vedi sotto per il codice di prova e il risultato.

Codice :

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");

  }

Eseguimi su ideone

Risultato :

100000 iterazioni per l'aggiunta di un singolo testo

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

10000 iterazioni per l'aggiunta di un singolo testo

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

1
  • StringBuffer è thread-safe ma StringBuilder non è thread-safe.
  • StringBuilder è più veloce di StringBuffer.
  • StringBuffer è sincronizzato mentre StringBuilder non è sincronizzato.

1

StringBuffer è sincronizzato e thread-safe, StringBuilder non è sincronizzato e più veloce.


Questa differenza è stata data in tutte le altre risposte a questa domanda. Potresti evidenziare qualcosa di nuovo?
Nico Haase,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.