2012-10-06 9 views
5

Ho bisogno di chiedere come viene implementato il pool di thread per avere un numero costante di thread in esecuzione ogni volta che si verifica l'invio di attività. (In esecutore evitare ogni creazione filetto tempo e soppressione sovraccarico)Come possiamo salvare un thread per l'attività successiva dopo l'esecuzione in java (Implementazione del pool di thread)

executor.submit(Runnable) 

Diciamo creiamo dei fili in partenza e quando compito venire assegniamo compito loro (Thread) utilizzando qualsiasi impl coda. Ma dopo aver completato s compito come potrebbe un ritorno filo alla piscina di nuovo quando come per il ciclo di vita del filo dice che

"Dopo l'esecuzione del suo metodo run va in stato terminato e non può essere usato di nuovo"

Non riesco a capire come funziona il pool di thread per il numero costante di thread per l'esecuzione di qualsiasi attività nella coda.

Sarebbe bello se qualcuno potesse fornirmi un esempio di riutilizzo dei thread dopo il completamento dell'attività.

!! Grazie in anticipo. !!

+0

Concettualmente è facile. Si avvia un numero fisso di thead i cui metodi di esecuzione sono in attesa su una coda. Si inviano richieste di lavoro alla coda, i metodi di esecuzione rimuovono le richieste e eseguono la richiesta di lavoro. Quindi tornano ad aspettare di nuovo in coda. Il trucco sta nel trovare il giusto tipo di coda - ce ne sono una mezza dozzina nel JDK, ma solo uno speciale (l'ultimo che ho visto) adatto a questo, ed era nascosto in un angolo. –

risposta

2

"Dopo esecuzione del metodo run va in stato chiuso e non può essere utilizzato nuovamente"

non termina la sua run() Invece ha un ciclo che gestisce il run() dei compiti che fornisci.


Semplificando il modello di pool di thread in modo drammatico si dispone di un codice simile a questo.

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 
      } 
     } 
    } 
} 

In questo esempio, si può vedere che, mentre la corsa() di ciascun compito completa, il run() del filo stesso non fino alla piscina è arresto.

+0

Ma se eseguiamo direttamente il metodo run, non verrà generato alcun thread. Esegue solo il metodo. Quindi vuol dire che execute (in impl personalizzato) può accettare qualsiasi attività che avrà lo stesso contratto (come Runnable ha eseguito()) e dobbiamo chiamare quel metodo di contratto nel thread del pool. Non è possibile utilizzare Runnable o Callable come attività? – Virendra

+0

Ho aggiunto un esempio. Penso che tu stia partendo dal presupposto che quando runtime.run() ritorna, qualcosa di speciale accade quando è solo una chiamata al metodo come qualsiasi altra. Una discussione si interrompe quando non c'è più nulla da fare. BTW UncaughtExceptionHandler può essere chiamato dopo l'esecuzione di run() in modo che un thread non termini immediatamente. –

0

Potete dare un'occhiata qui: http://www.ibm.com/developerworks/library/j-jtp0730/index.html per maggiori dettagli e un esempio di implementazione. I thread nel pool attenderanno se la coda è vuota e ognuno avvierà i messaggi dopo aver ricevuto la notifica che la coda ha alcuni elementi.

+0

stessa domanda qui. Perché è necessario avere compiti come Runnable o Callable quando il loro unico uso è chiamare il loro metodo contrattuale. r = (Runnable) queue.removeFirst(); r.run(); È necessario avere solo Runnable. possiamo importare qualsiasi altro oggetto che abbia eseguito il metodo. Come il suo obiettivo finale è quello di essere chiamato utilizzando thread di pooling non più di questo? – Virendra

0

ExecutorService executor = Executors.newFixedThreadPool(2);

- Quanto sopra dichiarato creare lo ThreadPool con dimensione fissa di 2.

executor.execute(new Worker());

- Questa istruzione prende un'istanza della classe lavoratore che ha attuato Runnable Interfaccia.

- Ora qui lo Executors è un oggetto intermedio che esegue l'attività. Che gestisce gli oggetti thread.

- Eseguendo la dichiarazione di cui sopra il metodo run() verrà eseguito, e una volta il metodo run() completa, il filo doesnot andare in stato di morto, ma si muove di nuovo in piscina, in attesa di avere un altro lavoro assegnato ad esso, quindi può ancora una volta passare in stato Runnable e quindi a correre, tutto questo è gestito da Executor.

executor.shutdown();

- che questo arresto dichiarazione volontà esecutori stesso, movimentazione grazia la chiusura di tutti i fili da essa gestiti .. shutdown() su quell'oggetto centrale, che a sua volta potrebbe terminare ciascuna delle esecutori registrati .

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

- Prima di tutto Runnable ha un metodo run(), che non possono tornare nulla, e il metodo run() non può lanciare un'eccezione controllata, quindi richiamabile è stato introdotto in Java 5, che è di tipo parametrico, e ha un metodo chiamato call(), ed è in grado di ritornare e lanciare eccezioni controllate.

ora vedere questo esempio:

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

t.run(); 

t.start(); 

-t.run() è solo una semplice chiamata al metodo run(), questo non si estenderà un thread of execution.

-t.start(), mentre si prepara per le cose importanti per la initialization del thread of execution, e poi chiamate il metodo run() del Runnable, e poi assegnare il Task al nuova formazionethread of execution e restituisce rapidamente ....

I thread in Java diventano una necessità quando si utilizza Swing e AWT. Principalmente il componente della GUI.

+0

@Vivek puoi rispondere alla domanda che ho posto sotto la domanda. perché eseguire come Runnable o Callable. Posso dare qualsiasi oggetto che ha il metodo run() in esso. Come thread di pool sta chiamando solo run() non crea alcun thread da esso. Quindi non è necessario eseguire Runnable? – Virendra

+0

@Virendra si prega di vedere la mia risposta modificata ..... –

+0

quindi nel caso dell'esecutore, t.run() funziona poiché non stiamo creando alcuna chiamata t.start() quando si esegue l'attività. Quindi questo è come fornire qualsiasi attività che potrebbe non essere l'implementazione di Runnable ma ha il metodo run(). Come Esecutore di PoolWorker solo l'esecuzione del metodo run (come t.run()) non usa le qualità del thread nell'attività? – Virendra

0

Sono totalmente d'accordo con Peter ma voglio aggiungere passaggi relativi al flusso di esecuzione di ExecutorService, per una chiara comprensione.

  • Se si crea piscina (piscina fisso dimensioni) di fili che non significa che le discussioni sono state create.
  • Se si invia e/o eseguire nuove attività (Runnuble o Callable) nuovo thread verrà creato sporge se conteggio di thread creati < dimensioni della piscina
  • thread creati non tornare alla piscina, le discussioni possono attendere per il nuovo valore nel bloccare in coda, questo punto possiamo chiamare RITORNARE ALLA PISCINA
  • Tutti i thread degli exec pool come descritto sopra.
1

Di solito cosa succede quando utilizziamo il pool di thread, il suo metodo Run interno è forzato a eseguire iterativamente. Fino a quando non ci sono attività disponibili nella coda.

nell'esempio seguente pool.removeFromQueue() verrà eseguito in modo iterativo.

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; 
    } 

bisogno di progettare il vostro pool di thread

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(); 
     } 
    }