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

Я понимаю идею исполнителя, но paramate r меня смущает. Я использовал:Сложность в понимании 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; 
    }); 

глубже и результат:

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 в настоящее время передается в качестве параметра конструктору Thread объекта.

  1. Как простое письмо r, указывающее, что объект передается является ThreadPoolExecutor?
  2. Как может быть ThreadPoolExecutor в качестве параметра, если он не реализует Runnable в соответствии с требованиями стандарта Thread's?

Если бы кто-то мог предоставить мне не-лямбда-версию кода, это было бы очень полезно для моего понимания.

ответ

15

newSingleThreadExecutor принимает ThreadFactory в качестве аргумента. ThreadFactory определяет один метод newThread, который принимает Runnable в качестве аргумента и возвращает Thread.

Лямбда может иметь больше смысла для вас, если мы указываем тип r явно:

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

Теперь это более очевидно, что это определение для тела newThread.

За исключением того, что поскольку лямбда немедленно передается в качестве аргумента методу, который принимает ThreadFactory, компилятор может сделать вывод о том, что тип r должен быть Runnable. Поэтому его можно опустить.

Без лямбды, этот код преобразуется в следующее анонимное определение класса и конкретизации:

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

Как простое письмо r, указывающее, что объект передается является ThreadPoolExecutor?

Тип r Runnable, потому что целевой тип выражения лямбда определяет его единственный метод таким образом.

Объект, который вы видите, является фактически ThreadPoolExecutor$Worker, который является частным внутренним классом ThreadPoolExecutor, который реализует Runnable.

Как с ThreadPoolExecutor проходимый в качестве параметра, если он не реализует Runnable в соответствии с требованиями по Thread «s конструктор?

См. Выше (r is Runnable).

+0

Спасибо, Radiodef. Теперь я полностью понимаю этот код.Где я могу узнать больше о нотах типа outerclass $ innerclass? - Спецификации языка Java? – user465001

+2

Я рад объяснить это. Также не так много узнать о '' '. Когда вы ссылаетесь на вложенный или внутренний класс в коде, вы используете 'Outer.Inner', но обычно он скомпилирован в класс под названием' Outer $ Inner'. «$» Является допустимым символом для всех идентификаторов, но обычно считается зарезервированным для внутренних механизмов. http://stackoverflow.com/q/7484210/2891664 – Radiodef

+0

Еще раз спасибо, Radiodef! – user465001

Смежные вопросы