2012-10-06 15 views
5

Necesito preguntar cómo se implementa la agrupación de subprocesos para tener un número constante de subprocesos cada vez que se produce el envío de tareas. (En Ejecutor para evitar la creación de cada hilo de tiempo y eliminación de arriba)¿Cómo podemos guardar un hilo para la próxima tarea después de su ejecución en java? (Implementación del conjunto de subprocesos)

executor.submit(Runnable) 

digamos que creamos algunos hilos en el inicio y cuando vienen tarea se le asigna la tarea a ellos (Tema) usando cualquier impl cola. Pero después de completar la tarea que s ¿cómo podría una vuelta de rosca a la piscina de nuevo cuando de acuerdo con el ciclo de vida del hilo dice que

"Después de la ejecución de su método run de que entre en estado terminado y no puede ser utilizado de nuevo"

No se entiende cómo funciona el grupo de subprocesos para tener una cantidad constante de subprocesos para la ejecución de cualquier tarea en su cola.

Sería genial si alguien pudiera darme un ejemplo de reutilización de hilo una vez completada la tarea.

!! Gracias de antemano. !!

+0

Conceptualmente es fácil. Inicia un número fijo de pads cuyos métodos de ejecución esperan en una cola. Envía solicitudes de trabajo a la cola, los métodos de ejecución dequeue las solicitudes y ejecuta la solicitud de trabajo. Luego vuelven a esperar en la cola nuevamente. El truco está en encontrar el tipo correcto de cola: hay media docena en el JDK, pero solo una especial (la última que miré) adecuada para esto, y estaba escondida en una esquina. –

Respuesta

2

"Después de la ejecución de su método run de que entre en estado terminado y no puede ser utilizado de nuevo"

No termina su run() su lugar, tiene un bucle que se ejecuta el run() de las tareas que le proporcionas


Simplificando el patrón de grupo de subprocesos de manera espectacular, tiene un código que se ve así.

final BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>(); 

public void submit(Runnable runs) { 
    tasks.add(runs); 
} 

volatile boolean running = true; 

// running in each thread in the pool 
class RunsRunnable implement Runnable { 
    public void run() { 
     while(running) { 
      Runnable runs = tasks.take(); 
      try { 
       runs.run(); 
      } catch(Throwable t) { 
       // handles t 
      } 
     } 
    } 
} 

En este ejemplo, se puede ver que mientras el run() de cada tarea se completa, el run() del hilo en sí no es hasta la piscina de apagado.

+0

Pero si ejecutamos el método run directamente, no se generará ningún hilo. Solo ejecutará el método. Entonces, significa que execute (en impl personalizado) puede aceptar cualquier tarea que tenga el mismo contrato (como Runnable se ha ejecutado()) y tenemos que llamar a ese método de contrato en el hilo del grupo. ¿No se puede usar Runnable o Callable como una tarea? – Virendra

+0

He agregado un ejemplo. Creo que está asumiendo que cuando Runtime.run() retorna, sucede algo especial cuando es solo una llamada a método como cualquier otra. Un hilo se detiene cuando no hay nada más que hacer. Por cierto, se puede invocar a UncaughtExceptionHandler después de que run() finalice para que un hilo no finalice inmediatamente. –

0

Puede ver aquí: http://www.ibm.com/developerworks/library/j-jtp0730/index.html para más detalles y un ejemplo de implementación. Los subprocesos del grupo esperarán si la cola está vacía y cada uno iniciará los mensajes de consumidores una vez que se les notifique que la cola tiene algunos elementos.

+0

misma pregunta aquí. Por qué es necesario tener la tarea como ejecutable o invocable cuando su único uso es llamar a su método de contrato. r = (Ejecutable) queue.removeFirst(); r.run(); Es necesario tener Runnable solamente. podemos proporcionar cualquier otro objeto que tenga el método de ejecución. Como su objetivo final es ser llamado usando hilos de agrupación no más que eso? – Virendra

0

ExecutorService executor = Executors.newFixedThreadPool(2);

- La declaración anterior creó un ThreadPool con tamaño fijo de 2.

executor.execute(new Worker());

- La declaración anterior toma una instancia de la clase trabajadora que ha implementado Runnable Interfaz.

- Ahora aquí el Executors es un objeto intermedio, que ejecuta la tarea. Que maneja los objetos de hilo.

- Mediante la ejecución de la declaración anterior del método run() se ejecutará, y una vez que el método run() finaliza, el hilo doesnot entrar en estado de muerte sino que se mueve de nuevo en la piscina, a la espera de tener otro trabajo asignado para ello, por lo que una vez más puede pasar al estado Runnable y luego a la ejecución, todo esto es manejado por los ejecutores.

executor.shutdown();

- La declaración anterior se apagará la propia Ejecutores, la manipulación con gracia el cierre de todos los subprocesos administrados por ella .. shutdown() en ese objeto central, que a su vez podría terminar cada uno de los ejecutores registrados .

////////// Edited Part////////////////////// 

- En primer lugar Ejecutable tiene un método run(), que no puede devolver nada, y el método run() no puede lanzar una excepción comprobada, tanto rescatable fue introducido en Java 5, que es de tipo paramétrico, y tiene un método llamado call(), y es capaz de devolver y lanzar excepciones Checked.

Ahora ver este ejemplo:

Thread t = new Thread(new Worker()); 

t.run(); 

t.start(); 

-t.run() es sólo una simple llamada al método run(), esto no tendrá una duración de unthread of execution.

-t.start() mientras que se prepara para las cosas importantes para la initialization del thread of execution, y luego llamadas el método run() del Runnable, y luego asignar la Task a la recién formadothread of execution y regresa rápidamente ....

Los hilos en Java se vuelven una necesidad cuando se usan Swing y AWT. Principalmente el componente GUI.

+0

@Vivek puede responder la pregunta que hice en la pregunta a continuación. por qué la tarea es ejecutable o invocable ¿Puedo dar cualquier obj que tenga el método run() en él? Como el agrupamiento de subprocesos está llamando solo a run() que no crea ningún subproceso. ¿Entonces no se requiere Runnable realmente? – Virendra

+0

@Virendra por favor vea mi respuesta editada ..... –

+0

por lo tanto, en caso de ejecutor, t.run() funciona ya que no estamos creando ninguna llamada t.start() al ejecutar la tarea. Esto es lo mismo que proporcionar cualquier tarea que no sea la implementación de Runnable pero tiene el método run(). Como PoolWorker de Executor solo ejecutando el método run (como t.run()) ¿no se usan las cualidades de subprocesos en la tarea? – Virendra

0

Estoy totalmente de acuerdo con Peter, pero quiero agregar pasos relacionados con el flujo de ejecución ExecutorService, para una comprensión clara.

  • Si crea piscina (piscina de tamaño fijo) de hilos que no significa que se crearon las discusiones.
  • Si envía y/o ejecutar nuevas tareas (Runnuble o Callable) nuevo hilo se creará adentra si el recuento de subprocesos creados < tamaño de la piscina
  • Creado hilos no regresan a la piscina, hilos puede esperar a un nuevo valor en el bloqueo cola, este punto podemos llamar DEVOLVER A PISCINA
  • Todos los hilos de ejecutivos de pool como Peter descritos anteriormente.
1

Por lo general, lo que sucede cuando utilizamos el grupo de subprocesos, su método dentro de ejecución se ejecuta de forma iterativa. Hasta que haya tareas disponibles en la cola.

en el ejemplo siguiente pool.removeFromQueue() se ejecutará de forma iterativa.

public class MyThread<V> extends Thread { 
    private MyThreadPool<V> pool; 
    private boolean active = true; 

    public boolean isActive() { 
     return active; 
    } 

    public void setPool(MyThreadPool<V> p) { 
     pool = p; 
    } 

    /** 
    * Checks if there are any unfinished tasks left. if there are , then runs 
    * the task and call back with output on resultListner Waits if there are no 
    * tasks available to run If shutDown is called on MyThreadPool, all waiting 
    * threads will exit and all running threads will exit after finishing the 
    * task 
    */ 
    @Override 
    public void run() { 
     ResultListener<V> result = pool.getResultListener(); 
     Callable<V> task; 
     while (true) { 
      task = pool.removeFromQueue(); 
      if (task != null) { 
       try { 
        V output = task.call(); 
        result.finish(output); 
       } catch (Exception e) { 
        result.error(e); 
       } 
      } else { 
       if (!isActive()) 
        break; 
       else { 
        synchronized (pool.getWaitLock()) { 
         try { 
          pool.getWaitLock().wait(); 
         } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
     } 
    } 

    void shutdown() { 
     active = false; 
    } 

necesidad de diseñar su grupo de subprocesos

public MyThreadPool(int size, ResultListener<V> myResultListener) { 
     tasks = new LinkedList<Callable<V>>(); 
     threads = new LinkedList<MyThread<V>>(); 
     shutDown = false; 
     resultListener = myResultListener; 
     for (int i = 0; i < size; i++) { 
      MyThread<V> myThread = new MyThread<V>(); 
      myThread.setPool(this); 
      threads.add(myThread); 
      myThread.start(); 
     } 
    } 
Cuestiones relacionadas