2008-09-17 6 views
10

¿es legal para un hilo llamar a this.start() dentro de su propio constructor? y si es así, ¿qué posibles problemas puede causar esto? Entiendo que el objeto no se habrá inicializado por completo hasta que el constructor se haya ejecutado por completo, pero aparte de esto ¿hay algún otro problema?llamando a thread.start() dentro de su propio constructor

Respuesta

1

Es legal, pero no acertado. La parte Thread de la instancia se inicializará por completo, pero es posible que su constructor no lo haga. Hay muy pocas razones para extender Thread, y usar trucos como este no ayudará a tu código.

2

Supongo que quiere hacer esto para que su código sea menos detallado; en lugar de decir

Thread t = new CustomThread(); 
t.start(); 
activeThreads.add(t); 

puede simplemente decir

activeThreads.add(new CustomThread()); 

También me gusta tener menos nivel de detalle, pero estoy de acuerdo con el resto de los encuestados que no se debe hacer esto. Específicamente, rompe la convención; cualquiera que esté familiarizado con Java y lea el segundo ejemplo supondrá que el hilo no se ha iniciado. Peor aún, si escriben su propio código de enhebrado que interactúa de alguna manera con el suyo, entonces algunos hilos necesitarán llamar al start y otros no.

Esto puede no parecer atractivo cuando trabajas solo, pero con el tiempo tendrás que trabajar con otras personas, y es bueno desarrollar buenos hábitos de codificación para que te resulte fácil trabajar con otros y código escrito con las convenciones estándar.

Sin embargo, si no le importan las convenciones y odia la verbosidad adicional, siga adelante; esto no causará ningún problema, incluso si intenta llamar al start varias veces por error.

2

Por cierto, si uno quiere verbosidad menor y aún así mantener el constructor con su semántica "estándar", se podría crear un método de fábrica:

activeThreads.add(CustomThread.newStartedThread()); 
+0

¿cómo es esto relevante para la cuestión del PO? – subsub

1

Se es "legal", pero creo el problema más importante es este: Una clase debe hacer una cosa y hacerlo bien.

Si su clase utiliza un subproceso internamente, entonces la existencia de ese subproceso no debería ser visible en la API pública. Esto permite la mejora sin afectar la API pública. Solución: extienda Runnable, no Thread.

Si su clase proporciona una funcionalidad general que, en este caso, sucede ejecutar en un hilo, entonces no desea limitarse a siempre creando un hilo. La misma solución aquí: extender Runnable, no Thread.

Para menos verbosidad En segundo lugar, sugiero usar un método de fábrica (por ejemplo, Foo.createAndRunInThread()).

13

Por razones de seguridad de la memoria, no debe exponer una referencia a un objeto o los campos de ese objeto a otro subproceso desde su constructor. Suponiendo que su hebra personalizada tenga variables de instancia, al iniciarla desde el constructor, se garantiza que violará las pautas del Modelo de memoria de Java. Ver Brian Goetz's Safe Construction Techniques para más información.

+1

¿Tiene comentarios sobre esta respuesta? No es incorrecto –

+1

¿Votación negativa? Por favor, localice una fuente si cree que esto está mal. Esto es correcto. –

+0

La respuesta no está enlatada en absoluto. A menos que use el constructor Runnable, puede hacer referencia a 'this' desde dentro de 'Thread # run' antes de que el constructor finalice, lo cual infringe las reglas de seguridad de la memoria. Por lo tanto, debes tener cuidado. –

3

También verá problemas extraños si la clase Thread se subclasifica. En ese caso, terminará con el hilo ejecutándose una vez que el super() salga, y cualquier cosa que la subclase pueda hacer en su constructor podría no ser válida.

@bill barksdale Si el hilo ya se está ejecutando, al llamar de nuevo se obtiene una IllegalThreadStateException, no obtiene 2 hilos.

1

Legal ... sí (con advertencias como se menciona en otros lugares). Aconsejable ... no.

Solo soy un olor que puedes evitar fácilmente. Si quieres que el hilo se inicie automáticamente, solo hazlo como Heinz Kabutz.

public class ThreadCreationTest { 
    public static void main(String[] args) throws InterruptedException { 
    final AtomicInteger threads_created = new AtomicInteger(0); 
    while (true) { 
     final CountDownLatch latch = new CountDownLatch(1); 
     new Thread() { 
     { start(); } // <--- Like this ... sweet and simple. 
     public void run() { 
      latch.countDown(); 
      synchronized (this) { 
      System.out.println("threads created: " + 
       threads_created.incrementAndGet()); 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       Thread.currentThread().interrupt(); 
      } 
      } 
     } 
     }; 
     latch.await(); 
    } 
    } 
} 
Cuestiones relacionadas