2014-11-06 28 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 ; 
}); 

Rozumiem ideę executora, ale paramater r wprowadza mnie w błąd. Użyłem:Masz problemy ze zrozumieniem 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; 
    }); 

kopać głębiej, a wynik jest:

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 jest przekazywana jako parametr do konstruktora Thread obiektu.

  1. Jaka jest prosta litera r wskazująca, że ​​przekazany obiekt to ThreadPoolExecutor?
  2. Jak można przejechać parametr ThreadPoolExecutor jako parametr, jeśli nie implementuje on Runnable zgodnie z wymaganiami konstruktora Thread's?

Jeśli ktoś mógłby mi dostarczyć wersję kodu, która nie jest lambdą, byłoby to bardzo korzystne dla mojego zrozumienia.

Odpowiedz

15

newSingleThreadExecutor pobiera ThreadFactory jako argument. ThreadFactory definiuje pojedynczą metodę newThread, która przyjmuje argument Runnable jako argument i zwraca wątek.

lambda może więcej sensu do Ciebie, jeśli mamy określić typ r wyraźnie:

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

Teraz jest to bardziej oczywiste jest to definicja ciała newThread.

Poza tym, że lambda jest natychmiast przekazywana jako argument do metody akceptującej ThreadFactory, kompilator jest w stanie wywnioskować, że typ r musi być Runnable. Dlatego można go pominąć.

Bez lambda, kod ten przekłada się na poniższej anonimowej definicji klasy i instancji:

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

Jak jest prosty list r wskazując, że obiekt jest przekazywana jest ThreadPoolExecutor?

Typ r można uruchomić, ponieważ docelowy typ wyrażenia lambda definiuje w ten sposób swoją pojedynczą metodę.

Obiekt, który widzisz minął, jest w rzeczywistości ThreadPoolExecutor$Worker, która jest prywatną wewnętrzną klasą ThreadPoolExecutor, która implementuje Runnable.

Jak się ThreadPoolExecutor zadowalający jako parametr, jeśli nie implementacji Runnable wymagane przez przez konstruktora Thread „s?

Zobacz wyżej (r to Runnable).

+0

Dzięki, Radiodef. W pełni rozumiem kod teraz.Gdzie mogę dowiedzieć się więcej o notacjach typu "outerclass $ innerclass" - specyfikacji języka Java? – user465001

+2

Miło mi to wyjaśnić. Również nie ma o wiele więcej do nauczenia się o '$'. Kiedy odwołujesz się do zagnieżdżonej lub wewnętrznej klasy w kodzie, używasz 'Outer.Inner', ale zazwyczaj jest ona faktycznie kompilowana do klasy o nazwie' Outer $ Inner'. '$' Jest poprawnym znakiem dla wszystkich identyfikatorów, ale zwykle jest uważany za zarezerwowany dla mechanizmów wewnętrznych. http://stackoverflow.com/q/7484210/2891664 – Radiodef

+0

Jeszcze raz dziękuję, Radiodef! – user465001

Powiązane problemy