2012-03-21 30 views
7

Tengo una aplicación donde cuando un "juego" estadísticas, comienza un par de hilos diferentes. Empiezo los hilos de esta manera:Buena práctica para multi-threading

Thread thread = new Thread(new Runnable() 
{ 
    public void run() 
    { 
     //... 
    } 
}); 

thread.setName("killMeAtEnd"); 
thread.start(); 

Más tarde, cuando el juego termina tengo un método dispose() dentro del juego que ordena a través de todos los subprocesos que se ejecutan y termina todos los hilos que tienen el nombre de "killMeAtEnd" . Mi pregunta es, ¿es esta una buena práctica? Mi intención es mantener mi aplicación en funcionamiento rápido y libre de obstáculos, en mi experiencia Los hilos que se quedan "colgando" tienden a ralentizar el teléfono hasta que la aplicación finaliza. ¿Hay una mejor manera de hacer esto? ¿Vale la pena preocuparse por esto?

EDIT:

Aquí es mi dispose() si alguien estaba interesado. Este código está dentro de la clase Juego.

public void dispose() 
{ 
    Thread threads[] = (Thread[])Thread.getAllStackTraces().keySet().toArray(); 
    for(int x=0;x<threads.length;x++) 
    { 
     Thread thread = threads[x]; 
     if(thread.getName().equalsIgnoreCase(KILL)) 
     { 
      try 
      { 
       thread.interrupt(); 
      }catch(Exception e){Log.e(Viewer.GAME,Log.getStackTraceString(e));} 
      thread = null; 
     } 
    } 
} 

public static final String KILL = "endOnDispose"; 
+0

Obtener stacktraces es bastante caro, por lo que sería más eficiente si guardara 'threads []' mientras crea los threads y hace que 'dispose (Thread [] threads) '. ¿Hay otros hilos que continúan ejecutándose cuando termina el juego o es para evitar que elimines el hilo de la interfaz de usuario? – zapl

+0

Cuando el "juego" termina, la Actividad no termina, se mueve a otra cosa. – John

Respuesta

4

Usted tiene la idea correcta, pero hay algunas áreas de mejora:

  1. en lugar de consultar el sistema para todos los subprocesos que se ejecutan, sólo tiene que añadir sus hilos a una lista cada vez que se crea. A continuación, puede finalizar todos los hilos que creó o esperar a que finalicen (unirse).
  2. La interrupción solo interrumpe un hilo en estado de bloqueo, por lo que debe tener un indicador adicional que el hilo verifique periódicamente (es decir, después de cada "ciclo de trabajo").
  3. Captura la excepción de interrupción dentro de su hilo y manejarlo (es decir, salir con gracia).
+0

+1 ¡Gracias! Terminé poniendo todos mis hilos en una lista y luego matándolos una vez que el juego estaba hecho. – John

3

Esto no es necesariamente una mala solución, pero hay algunos problemas:

  • Si sus hilos son hilos de trabajo de la clase que se encargan de una tarea a la terminación, hay probablemente un mejor diseño en el que el hilo se termine. En otras palabras, posiblemente haya un mejor flujo de ejecución, que no requiere ser asesinado al final.

  • Cuando dice "ordenar a través de todos los hilos en ejecución ...", me imagino que está viendo TODOS los hilos en ejecución en la JVM? como en algo similar a this SO question? Si ese es el caso, ¿por qué no solo mantienes una referencia a todos los hilos que posee tu juego y luego específicamente los matas? A diferencia de simplemente buscar "killMeAtEnd"; No puedo pensar en cómo su estrategia podría salir mal, pero parece un poco más limpio hacer un seguimiento de sus hilos.

Definitivamente es una buena práctica mantener los hilos limpios. Si sus hilos están haciendo algo menos específico, orientado a tareas (por ejemplo, esperando la red io, o algo así), entonces mi primera sugerencia es algo irrelevante. Yo solo recomendaría ser muy cuidadoso con el diseño de cómo mantener sus hilos limpios, porque los errores con hilos pueden ser un gran dolor.

+0

+1 ¡gracias por la ayuda! – John

0

La clase ExecutorService ya existe para manejar este tipo de problema.

Realice todas sus tareas de hilos para el ExecutorService.

Cuando el juego finaliza, apaga el ExecutorService usando shutdownNow. Esto interrumpirá la interrupción de todos los hilos en el ExecutorService.Luego puede crear un nuevo ExecutorService cuando comience un juego nuevo.

Si se fija la cantidad de subprocesos, puede usar Executors.newFixedThreadPool() para crear el ExecutorService.

Si el número de subprocesos es variable, puede usar Executors.newCachedThreadPool para crear el ExecutorService.

Cuestiones relacionadas