ae pessoal queria saber qual a diferenca entre as duas classes… sei que a Stringbuilder não é segura em relação a threads segundo a kathy pois ainda nao estudei threads… mais a StringBuffer qual exatamente a diferença entre uma e outra?
É como a Kathy diz…
Camilo,
As duas classes têm o mesmo comportamento, a unica diferença mesmo é que a StringBuilder é Thread’s Safe, isso significa que se você vai utilizar um texto em uma unica Thread utilize StringBuilder, por não é sincronizada ela se torna mais rapida.
ta ai algo que eu queria ver. um benchmark no java 6 de stringbuilder e stringbuffer.
eu duvido muito que a velocidade seja muito diferente. alguem se habilita?
Legal você ter levantado isso!!
Não tenho muito experîência, e não encontrei nenhuma documentação sobre a performance das duas classes, mas encontrei alguns foruns sobre esse mesmo assunto:
http://forum.java.sun.com/thread.jspa?threadID=762884&messageID=4352865
http://forum.java.sun.com/thread.jspa?threadID=652378
A duvida permanece, mas parece que existe um ganho de performance… mesmo que minimo… E na duvida eu vou continuar usando a StringBuilder sempre que ela se mostrar viável…
[]'s
Adicionei uns 1000000 strings nas duas aqui e ambas levaram 297 milisegundos.
Ah, a VM é 1.6.0.
Como vc fez para conometrar o tempo?
Ate helloWord aqui em casa o tempo varia e segundos.
JDK 1.5.09
Netbeans 5.5
Passa o Codigo Mauricio
bom, eu li mais uma vez a parte q a kathy fala sobre isso… e achei a resposta… e vcs reforçaram valeu ai… e StringBuilder teoricamente é mais rapida por nao ser sincronizada em relação a Threads… mais eu usei as duas e nao percebi a diferença em questao de velocidade mais ja que eh recomendado a StringBuilder vou com ela… entao queria entender a essencia delas… mesmo… valeu galea mais eu to usando o java 1.5…
Realmente, a diferença é pequena.
Via de regra, uso o StringBuilder. Dificilmente você vai usar o StringBuilder de maneira sincronizada, como seria o caso do StringBuffer. Mesmo em uma aplicação multi-thread, provavelmente o método que montará a string será sincronizado e será o único que usará o builder.
A sincronização realmente tem seu peso, mas nesse caso, esse peso será insignificante para a maior parte das aplicações.
E pessoal, cuidado com os micro-benchmarks. A JVM tem muitas otimizações que vão fazer códigos bem pequenos não terem diferença de tempo. Por exemplo, ela é capaz de perceber que um objeto gravado e não lido será descartado e eliminar completamente a sua criação. Um tema amplamente discutido é como fazer benchmark no java, mas algumas dicas podem ser encontradas em
http://www.javaperformancetuning.com/
Pessoal, fiz um humilde teste onde podemos ver que o uso da classe StringBuffer mostra uma grande diferença de tempo com relação a StringBuilder.
Obviamente que foi necessário utilizar Thread para que a diferença fosse notável.
Resultado aqui na minha máquina:
StringBuffer aprox. 1047ms.
StringBuilder aprox. 281ms.
–
Comentem e descomentem as linhas no inicio do código para alternar a execução do código entre StringBuffer e StringBuilder.
Não esqueçam de recomplilar!
public class Tester implements Runnable {
static StringBuffer buffer = new StringBuffer();
// static StringBuilder buffer = new StringBuilder();
public void run() {
for (int i = 0; i < 1000000; i++) {
buffer.append(getString());
}
}
public static void main(String[] args) throws InterruptedException {
Tester t = new Tester();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
long time = System.currentTimeMillis();
t1.start();
t2.start();
while(t1.isAlive() || t2.isAlive() )
Thread.sleep(1);
System.out.println(System.currentTimeMillis() - time + "ms.");
}
public static String getString() {
return "ABC";
}
}
Testem aí… :thumbup:
Mas ai nao faz sentido, porque sua StringBuilder pode ficar com os caracteres em poscioes todas erradas, tamanho final da String errada, buracos no meio da String, etc
Sim, é verdade.
Mas onde está a diferença entre as classes? Justamente no fato de os métodos da StringBuffer serem synchronized, deste modo, somente fazendo uso da desvantagem de tempo que um método synchronized possui é que podemos ver alguma diferença de tempo. Será quer fora isso ainda existe outra coisa que pode resultar em diferença de performance?
[quote=rmarin]Sim, é verdade.
Mas onde está a diferença entre as classes? Justamente no fato de os métodos da StringBuffer serem synchronized, deste modo, somente fazendo uso da desvantagem de tempo que um método synchronized possui é que podemos ver alguma diferença de tempo. Será quer fora isso ainda existe outra coisa que pode resultar em diferença de performance?[/quote]
O que o Paulo disse é válido. Testando desse jeito não faz sentido. Se você tem mais de um thread acessando o StringBu* você vai ter que ou utilizar StringBuffer ou cuidar da sincronização você mesmo.
A questão aqui é que mesmo quando você só tem um thread acessando o StringBuffer a sincronização causa um overhead. E a pergunta é se esse overhead é significante ou não.
Prezado CamiloLopes
Seguem as teorias para ajudar em sua prática, espero ter contribuido.
Rodrigo
StringBuffer
Uma seqüência enfí-segura, mutable dos caráteres. Um amortecedor da corda é como uma corda, mas pode ser modificado. Em algum ponto a tempo contem alguma seqüência particular dos caráteres, mas o comprimento e o índice da seqüência podem ser mudados com determinadas chamadas do método. Os amortecedores da corda são seguros para o uso por linhas múltiplas. Os métodos são sincronizados onde necessário de modo que todas as operações em todo o exemplo particular se comportem como se ocorrem em alguma ordem de série que é consistente com a ordem das chamadas do método feitas por cada uma das linhas individuais envolvidas. As operações principais em um StringBuffer são a adição e introduzem os métodos, que são sobrecarregados para aceitar dados de qualquer tipo. Cada um converte eficazmente uma referência dada a uma corda e então adiciona ou introduz os caráteres dessa corda ao amortecedor da corda. O método da adição adiciona sempre estes caráteres na extremidade do amortecedor; o método da inserção adiciona os caráteres em um ponto especificado. Para o exemplo, se z consultasse a um objeto do amortecedor da corda cujos os índices atuais fossem “começo”, a seguir a chamada z.append(“le do método”) faria com que o amortecedor da corda contivesse “o startle”, visto que z.insert(4, “o le”) alterariam o amortecedor da corda para conter “o starlet”. No general, se o sb consultar a um exemplo de um StringBuffer, a seguir em sb.append(x) tem o mesmo efeito que sb.insert(sb.length(), x). Sempre que uma operação ocorre envolvendo uma seqüência da fonte (tal como a adição ou a introdução de uma seqüência da fonte) esta classe sincroniza somente no amortecedor da corda que executa a operação, não na fonte. Cada amortecedor da corda tem uma capacidade. Tão por muito tempo como o comprimento da seqüência do caráter contida no amortecedor da corda não excede a capacidade, não é necessário alocar uma disposição interna nova do amortecedor. Se o amortecedor interno transbordar, está feito automaticamente maior. Como de JDK 5 da liberação, esta classe foi suplementada com uma classe equivalente projetada para o uso por uma única linha, StringBuilder. A classe de StringBuilder deve geralmente ser usada na preferência a esta, porque suporta todas as mesmas operações mas é mais rápida, porque não executa nenhuma sincronização.
StringBuilder
Uma seqüência mutable dos caráteres. Esta classe fornece um API compatível com o StringBuffer, mas com nenhuma garantia da sincronização. Esta classe é projetada para o uso como a gota- na recolocação para StringBuffer nos lugares onde o amortecedor da corda era usado por uma única linha (como é geralmente o caso). Onde possível, se recomenda que esta classe esteja usada na preferência a StringBuffer porque será mais rápida sob a maioria de execuções. As operações principais em um StringBuilder são a adição e introduzem os métodos, que são sobrecarregados para aceitar dados de qualquer tipo. Cada um converte eficazmente uma referência dada a uma corda e então adiciona ou introduz os caráteres dessa corda ao construtor da corda. O método da adição adiciona sempre estes caráteres na extremidade do construtor; o método da inserção adiciona os caráteres em um ponto especificado. Para o exemplo, se z consultasse a um objeto do construtor da corda cujos os índices atuais fossem “começo”, a seguir a chamada z.append(“le do método”) faria com que o construtor da corda contivesse “o startle”, visto que z.insert(4, “o le”) alterariam o construtor da corda para conter “o starlet”. No general, se o sb consultar a um exemplo de um StringBuilder, a seguir em sb.append(x) tem o mesmo efeito que sb.insert(sb.length(), x). Cada construtor da corda tem uma capacidade. Tão por muito tempo como o comprimento da seqüência do caráter contida no construtor da corda não excede a capacidade, não é necessário alocar um amortecedor interno novo. Se o amortecedor interno transbordar, está feito automaticamente maior. Os exemplos de StringBuilder não são seguros para o uso por linhas múltiplas. Se tal sincronização for requerida então recomenda-se que StringBuffer esteja usado.
Segue ai pessoal, um exemplo pratico da diferença.
public class Main {
public static void main(String[] args) {
int N = 77777777;
exemploComBuffer(N);
exemploComBuilder(N);
}
private static void exemploComBuilder(int N) {
long t = System.currentTimeMillis();
StringBuilder sb = new StringBuilder();
for (int i = N; i-- > 0;) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
private static void exemploComBuffer(int N) {
long t = System.currentTimeMillis();
StringBuffer sb = new StringBuffer();
for (int i = N; i-- > 0;) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
}