new - stringbuilder java api 8




Differenza tra StringBuilder e StringBuffer (20)

Qual è la principale differenza tra StringBuffer e StringBuilder ? C'è qualche problema di prestazioni al momento di decidere su uno di questi?


Abbastanza buona domanda

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.


Ma necessario per ottenere la chiara differenza con l'aiuto di un esempio?

StringBuffer o StringBuilder

Basta usare StringBuilder meno che non si stia davvero provando a condividere un buffer tra i thread. StringBuilder è il fratello minore non sincronizzato (meno overhead = più efficiente) della classe StringBuffer sincronizzata originale.

StringBuffer arrivato per primo. Sun era interessato alla correttezza in tutte le condizioni, quindi lo hanno reso sincronizzato per renderlo thread-safe per ogni evenienza.

StringBuilder venuto dopo. La maggior parte degli usi di StringBuffer erano a thread singolo e pagavano inutilmente il costo della sincronizzazione.

Poiché StringBuilder è una sostituzione drop-in per StringBuffer senza la sincronizzazione, non ci sarebbero differenze tra gli esempi.

Se si sta tentando di condividere tra thread, è possibile utilizzare StringBuffer , ma considerare se è necessaria la sincronizzazione di livello superiore, ad esempio, forse, anziché utilizzare StringBuffer, se si sincronizzano i metodi che utilizzano StringBuilder.


Ecco il risultato del test delle prestazioni per String vs StringBuffer vs StringBuilder . Infine, StringBuilder ha vinto il test. Vedi sotto per codice di test e 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 iterazione per aggiungere un singolo testo

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

10000 iterazione per aggiungere un singolo testo

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

Fondamentalmente, i metodi StringBuffer sono sincronizzati mentre StringBuilder no.

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

Questo è praticamente tutto.

Citazione StringBuilder :

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

Quindi è stato fatto per sostituirlo.

Lo stesso è successo con Vector e ArrayList .


In thread singoli, StringBuffer non è molto più lento di StringBuilder , grazie alle ottimizzazioni JVM. E nel multithreading, non puoi usare tranquillamente un StringBuilder.

Ecco il mio 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
Tamponi: 23
Builder: 7!

Quindi i builder sono più veloci dei buffer e WAY sono più veloci della concatenazione di 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 StringBuffer richiede 157 ms per 100000 accodamenti. Non è lo stesso test, ma rispetto ai precedenti 37 ms, si può tranquillamente supporre che gli accodamenti StringBuffer siano più lenti con l'uso del multithreading . La ragione è che JIT / hotspot / compiler / qualcosa fa ottimizzazioni quando rileva che non è necessario controllare i blocchi.

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

La conclusione è che non devi inseguire gli StringBuffer. E dove hai discussioni, pensa a quello che stanno facendo, prima di provare a guadagnare qualche nanosecondo.


La principale differenza è che StringBuffer è sincronizzato ma StringBuilder è. Se è necessario utilizzare più di un thread, viene consigliato StringBuilder Tuttavia, come per la velocità di esecuzione StringBuilder è più veloce di StringBuffer , perché non sincronizzato.


Meglio usare StringBuilder poiché non è sincronizzato e quindi offre prestazioni migliori. StringBuilder è una sostituzione drop-in del precedente StringBuffer.


Non ci sono differenze di base tra StringBuilder e StringBuffer, esistono solo poche differenze tra loro. In StringBuffer i metodi sono sincronizzati. Ciò significa che in un momento solo un thread può operare su di essi. Se ci sono più thread, il secondo thread dovrà attendere il completamento 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 in caso di StringBuffer sono basse.

D'altra parte StringBuilder non è sincronizzato. Ciò significa che in un momento più thread possono operare sullo stesso oggetto StrinBuilder allo stesso tempo. Questo rende il processo molto veloce e quindi le prestazioni di StringBuilder sono alte.


Poiché StringBuffer è sincronizzato, richiede uno sforzo extra, quindi basato su perforamance, è un po 'lento rispetto a StringBuilder .



StringBuilder è molto più veloce di StringBuffer perché non è sincronizzato.

Qui hai più idea del costo della sincronizzazione

Lasciare prendere a livello di codice quanto StringBuilder più veloce di StringBuffer

public class Test{  
 public static void main(String[] args){  
    long startTime = System.currentTimeMillis();  
    StringBuffer sb = new StringBuffer("Yasir");  
    for (int i=0; i<10000; i++){  
        sb.append("Shabbir");  
    }  
    System.out.println("Time taken by StringBuffer: " + (System.currentTimeMillis() - startTime) + "ms");  
    startTime = System.currentTimeMillis();  
    StringBuilder sb2 = new StringBuilder("Yasir");  
    for (int i=0; i<10000; i++){  
        sb2.append("Shabbir");  
    }  
    System.out.println("Time taken by StringBuilder: " + (System.currentTimeMillis() - startTime) + "ms");  
}  
}  

Produzione

Tempo impiegato da StringBuffer: 16ms

Tempo impiegato da StringBuilder: 0ms


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

Dai StringBuilder :

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


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

    }
}


String è immutabile.

StringBuffer è un mutabile e sincronizzato.

StringBuilder è anche mutabile ma non è sincronizzato.


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


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

Leggi il tutorial per maggiori dettagli.


StringBuilder e StringBuffer sono quasi la stessa cosa. La differenza è che StringBuffer è sincronizzato e StringBuilder no. Sebbene, StringBuilder sia più veloce di StringBuffer , la differenza di prestazioni è minima. StringBuilder è la sostituzione di SUN di StringBuffer . Evita solo la sincronizzazione da tutti i metodi pubblici. Piuttosto, la loro funzionalità è la stessa.

Esempio di buon utilizzo:

Se il tuo testo sta per cambiare ed è utilizzato da più thread, allora è meglio usare StringBuffer . Se il testo sta per cambiare ma viene utilizzato da un singolo thread, quindi utilizzare StringBuilder .


StringBuffer:

  • Multi thread
  • sincronizzato
  • Lento di StringBuilder

StringBuilder

  • Singolo-Thread
  • Non-sincronizzato
  • Più veloce che mai String

StringBuffer è mutabile. Può cambiare in termini di lunghezza e contenuto. StringBuffers sono thread-safe, il che significa che hanno metodi sincronizzati per controllare l'accesso in modo che solo un thread possa accedere a un codice sincronizzato dell'oggetto StringBuffer alla volta. Pertanto, gli oggetti StringBuffer sono generalmente sicuri da utilizzare in un ambiente multi-thread in cui più thread potrebbero tentare di accedere allo stesso oggetto StringBuffer allo stesso tempo.

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







stringbuffer