2014-11-06 20 views
8
private ExecutorService exec = Executors.newSingleThreadExecutor(r -> { 
    Thread t = new Thread(r); 
    t.setDaemon(true); // allows app to exit if tasks are running 
    return t ; 
}); 

Capisco l'idea dietro un esecutore ma, il parametro r mi confonde. Ho usato:Difficoltà a capire un Java 8 Lambda

final ExecutorService exec = Executors.newSingleThreadExecutor(r -> { 
     Thread t = new Thread(r); 
     System.out.println("Class of r: " + r.getClass()+ ". r to string: " + r.toString()); 
     System.out.println("Class of t: " + t.getClass() +". Name of t: "+ t.getName()); 
     t.setDaemon(true); 
     return t; 
    }); 

scavare più a fondo e il risultato è:

Class of r: class java.util.concurrent.ThreadPoolExecutor$Worker. r to string: [email protected][State = -1, empty queue] 
Class of t: class java.lang.Thread. Name of t: Thread-3 

r viene passato come parametro al costruttore Thread oggetto.

  1. Come è la semplice lettera r che indica che l'oggetto passato è un ThreadPoolExecutor?
  2. In che modo un parametro ThreadPoolExecutor è passabile come parametro se non implementa Runnable come richiesto dal costruttore di Thread's?

Se qualcuno potrebbe fornirmi anche una versione non codificata del codice, sarebbe di grande beneficio per la mia comprensione.

risposta

15

newSingleThreadExecutor accetta ThreadFactory come argomento. ThreadFactory definisce un singolo metodo newThread che accetta un Runnable come argomento e restituisce una discussione.

La lambda può rendere più senso per voi se specifichiamo il tipo di r esplicitamente:

(Runnable r) -> { 
    Thread t = new Thread(r); 
    return t; 
} 

ora è più evidente questa è una definizione per il corpo di newThread.

Tranne che dal momento che lambda viene immediatamente passato come argomento a un metodo che accetta un ThreadFactory, il compilatore può dedurre che il tipo di r deve essere eseguibile. Pertanto può essere omesso.

Senza lambda, questo codice si traduce al seguente definizione di classe anonima e di istanze:

private ExecutorService exec = Executors.newSingleThreadExecutor(
    new ThreadFactory() { 
     @Override 
     public Thread newThread(Runnable r) { 
      Thread t = new Thread(r); 
      t.setDaemon(true); 
      return t; 
     } 
    } 
); 

Come è la semplice lettera r che indica che l'oggetto passato è un ThreadPoolExecutor?

Il tipo di r è eseguibile perché il tipo di destinazione dell'espressione lambda definisce il suo unico metodo in questo modo.

L'oggetto che si sta visualizzando è in realtà un ThreadPoolExecutor$Worker che è una classe interna privata di ThreadPoolExecutor che implementa Runnable.

Come è un ThreadPoolExecutor passabile come parametro se non implementa Runnable come richiesto dal costruttore per Thread s'?

Vedi sopra (r è un Runnable).

+0

Grazie, Radiodef. Capisco perfettamente il codice ora.Dove posso trovare ulteriori informazioni sulle notazioni di tipo 'outerclass $ innerclass' - le specifiche del linguaggio Java? – user465001

+2

Sono felice di spiegarlo. Inoltre non c'è molto di più da imparare sul '$'. Quando si fa riferimento a una classe nidificata o interiore nel codice si utilizza 'Outer.Inner', ma in genere viene compilato in una classe denominata' Outer $ Inner'. Il '$' è un carattere valido per tutti gli identificatori ma di solito è considerato riservato ai meccanismi interni. http://stackoverflow.com/q/7484210/2891664 – Radiodef

+0

Grazie ancora, Radiodef! – user465001