2009-03-10 28 views
13

Estoy construyendo una cadena de múltiples piezas y quiero usar StringBuffer o StringBuilder para hacerlo. A partir de los documentos de Java 5, veo que StringBuilder se prefiere cuando sea posible, con la advertencia de queJava StringBuilder and Thread Safety

Las instancias de StringBuilder no son seguros para su uso por varios subprocesos.

De esta declaración, entiendo que no debería tener una única instancia StringBuilder compartida por varios subprocesos. Pero ¿qué pasa con este caso:

//Is this safe? 
//foo() is called simultaneously by multiple threads 
String foo(String a, String b) { 
    return new StringBuilder(a).append(b).toString(); 
} 

Aquí podría haber múltiples hilos en la función, al mismo tiempo, utilizando la clase StringBuilder al mismo tiempo (por ejemplo, el acceso simultáneo de variables estáticas, si los hay), pero cada hilo tendría su propia instancia separada de StringBuilder. De la documentación, no puedo decidir si esto cuenta como uso por múltiples hilos o no.

+0

Puede haber algún beneficio al hacer foo() un método estático también, ya que no toca ninguna variable de instancia. – Kip

+0

@Kip: Depende de la clase. Pero algunas veces es posible que desee realizar operaciones polimórficas y hacer que el método sea estático lo impedirá. – OscarRyz

+0

El uso de String.concat sería más rápido, pero creo que esto es solo un ejemplo. –

Respuesta

19

Eso está perfectamente bien. Las variables locales no tienen problemas con la seguridad de subprocesos, siempre que no accedan o muten las variables de instancia o clase.

11

Sí, eso es seguro, porque el objeto StringBuilder se usa solo localmente (cada hilo que llame a foo() generará su propio StringBuilder).

También debe tomar nota de que el código que envió es prácticamente idéntico al código de bytes generada por este:

String foo(String a, String b) { 
    return a + b; 
} 
+0

¿Cómo ve ese bytecode? – OscarRyz

+0

@Oscar: javap -c

+0

vea también: http://stackoverflow.com/questions/272535/how-do-i-decompile-java-class-files – Kip

4

acuerdo con las otras respuestas - sólo una nota.

Si hubo un caso en el que StringBuffer estaba siendo utilizado por varios hilos, probablemente sea un caso de uso completamente roto porque significaría que se estaba creando una sola secuencia en un orden casi aleatorio, por lo que no tendría sentido para hacer que el hilo StringBuffer sea seguro.

+0

Esa es la razón de ser de StringBuilder. La mayoría de las veces la sincronización no era necesaria. – OscarRyz

+0

Sí, lo que hace que se pregunte por qué no solo reescribieron StringBuffer en lugar de crear el StringBuilder paralelo. Para mantener la compatibilidad hacia atrás para esa aplicación que construye cadenas no deterministas? –

+1

¿Tal vez si estuviera usando un StringBuilder para algún tipo de registro en memoria de una aplicación multiproceso? Sin embargo, no estoy seguro de por qué harías eso ... – Kip

3

No estoy seguro de si este código es necesario, porque Java elige el StringBuilder automáticamente, supongo. Si no tiene un problema de rendimiento, vaya con a + b.

En caso de una necesidad de rendimiento, pruebe lo siguiente:

return new StringBuilder(
a.length() + b.length()).append(a).append(b).toString(); 

correctamente los tamaños de la memoria intermedia y evita que la máquina virtual de cambiar el tamaño y la creación de basura para recoger en el camino.

6

El código que tiene es seguro.

Este código no lo es.

public class Foo 
{ 
    // safe 
    private final static StringBuilder builder; 

    public static void foo() 
    { 
     // safe 
     builder = new StringBuilder(); 
    } 

    public static void foo(final String a) 
    { 
     // unsafe 
     builder.append(a); 
    } 

    public synchronized void bar(final String a) 
    { 
     // safe 
     builder.append(a); 
    } 
} 

Las variables locales que sólo hacen uso de datos locales no tienen hebras cuestiones. Solo puede tener problemas de seguridad de subprocesos una vez que comience a tratar con los datos que están visibles en la clase o en el método de instancia/nivel de variable.