2010-09-19 30 views
5

Estoy confundido en lo siguiente:
Para usar hilos en un programa Java, la forma más simple es extender la clase Thread e implementar la interfaz ejecutable (o simplemente implementar ejecutable).
Para iniciar la ejecución del subproceso. debemos llamar al método Thread start(), que a su vez llama al método run() del hilo. Y entonces el hilo comienza.
El método start() (a menos que sea incorrecto) se debe llamar exactamente y solo una vez para cada subproceso. Como resultado, las instancias de subprocesos no pueden reutilizarse a menos que de alguna manera el método de ejecución en sí mismo se ejecute en un ciclo infinito que facilite una implementación personalizada del reutilización del subproceso.
Ahora el javadoc link text dicereutilización de hilo java a través del ejecutor

llamadas a ejecutar reutilizará hilos construidos previamente si está disponible

No entiendo cómo esto se lleva a cabo. Proporciono en el método de ejecución del método ejecutor mi hilo personalizado, p.

ExecutorService myCachedPool = Executors.newCachedThreadPool(); 
    myCachedPool.execute(new Runnable(){public void run(){ 
    //do something time consuming 

    }}); 

¿Cómo se puede reutilizar esta hebra personalizada que delego en el marco ejecutor?
¿El ejecutor puede llamar al método start() más de 1 vez, mientras que nosotros no podemos en nuestros programas? ¿Estoy malentendiendo algo?

Gracias.

Respuesta

4

Tenga en cuenta que no es Executor que llama a start() - es ExecutorService. Y no, no está llamando al start() dos veces. No inicia la tarea que le asigna directamente usando Thread.start() ... en su lugar, inicia un hilo que conoce la cola de trabajo del grupo de subprocesos. El hilo básicamente esperará hasta que haya algo de trabajo que hacer, luego lo recogerá y lo ejecutará, antes de volver a esperar. Entonces, aunque el hilo realiza varias tareas, solo se llama a Thread.start() una vez.

EDITAR: A juzgar por los comentarios, está un poco confundido acerca de la diferencia entre Runnable (que es una tarea que debe ejecutarse) y Thread (que es lo que ejecuta las tareas).

El mismo subproceso puede ejecutar varias tareas. Para un ejemplo muy simple no se utiliza un grupo de subprocesos, considere esto:

(Ignorar los posibles problemas de seguridad hilo de utilizar un List<T> desde varios subprocesos.)

Se puede crear un montón de Runnable tareas capaz de hacer cosas diferentes, luego crea un solo MultiRunnable para ejecutarlos sucesivamente. Pase esa instancia de MultiRunnable al constructor Thread y luego, cuando inicie el hilo, ejecutará cada una de las tareas ejecutables originales. ¿Eso ayuda?

+0

@ Jon: Lo siento que te había perdido. Entonces, ¿los subprocesos internos del framework se reutilizan y no el ejecutable que paso como argumento para ejecutar? Mi hilo que delegue en el marco se volverá a crear instancias cada vez, pero por la misma instancia del hilo interno creado por el marco? – Cratylus

+0

@ user384706: Sí. Su ejecutable * no es * un hilo, es solo una tarea para ejecutar. Necesita diferenciar entre los dos; son muy diferentes. –

+0

@Jon: Muchas gracias. Lo único de lo que no estoy seguro es cuál es el beneficio de usar Executors.newCachedThreadPool(); Porque si mi clase que implementa el ejecutable (para una tarea) es cara de ser instanciada, no será reutilizada y el mismo hilo del marco, seguirá usando nuevas instancias de la tarea. Entonces, ¿qué ganaría con esta API? A menos que el concepto sea que cada clase que implemente ejecutable sea mínima. – Cratylus

5

No está llamando a start() más de una vez; en cambio, el hilo en la piscina nunca se completa, sino que se mantiene vivo, esperando. El código fuente está disponible para descargar si desea verlo.

Cada subproceso en el grupo de subprocesos puede simplemente wait() para que el ejecutor le proporcione un nuevo ejecutable, pero el propio método run() del subproceso no se ha completado. Simplemente espera que se le entregue un nuevo Runnable al Ejecutor.

+0

¿Quiere decir que en el javadoc donde dice "que los hilos previamente construidos serán reutilizados" no se refiere al ejecutable que paso a la ejecución, sino a los hilos internos del marco de ejecutores? Entonces mi Runnable se volverá a instanciar por el mismo hilo de grupo de hilos? ¿He entendido lo que estás diciendo? – Cratylus

+2

Su Runnable no será reinstalado. Su instancia de Runnable se otorgará a uno de los subprocesos en el grupo. Ese hilo tiene su propio método 'run()', que no es (no puede ser) reemplazado por el método 'run()' de su Runnable. El método run() de Thread invocará el método 'run()' de 'Runnable', y luego de que su' Runnable.run() 'termine, el hilo eventualmente (hay algo de contabilidad que debería hacerse) irá volver a 'esperar'. – jbindel

1

Para "iniciar" un hilo más de una vez, cree un ejecutable. Por ejemplo:

//NO 
private class T extends Thread { //not necessary to implement runnable 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    a.start(); 
    a.start(); //NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO 
} 

En cambio,

//Yes 
private class T implements Runnable { 
    public void run(){ 
     //... 
    } 
} 
void someMethod(){ 
    T a = new T(); 
    new Thread(a).start(); 
    new Thread(a).start(); //YES YES YES 
} 

También es posible hacer esto:

void someMethod(){ 
    final Runnable r = new Runnable(){ 
     public void run(){ 
      //... 
     } 
    }; 
    new Thread(r).start(); 
    new Thread(r).start(); 
} 
// r could also be a field of you class. 
Cuestiones relacionadas