ExecutorService & Lambdas - разница между .execute (() -> ...) и .execute () - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть класс, который реализует интерфейс Runnable и является задачей, которая после запуска будет выполняться бесконечно (длительный поток).

public class LongRunningTask implements Runnable {

    @Override
    public void run() {
        //stuff happening here
    }

}

Простое создание ExecutorService/ThreadPoolExecutor:

final ExecutorService executorService = Executors.newFixedThreadPool(8);

Если LongRunningTask действительно запущен / выполнен, я могу наблюдать его фактический результат, и поэтому я заметил это:

  • если я передам его для выполнения с executorService.execute(() -> new LongRunningTask());, он не будет выполнен вообще, и не будет никакого результата.

  • если я передам его для выполнения с executorService.execute(new LongRunningTask()); оно будет выполнено так, как должно быть, и будет результат.

В чем разница при использовании лямбда-синтаксиса () ->?

Ответы [ 2 ]

4 голосов
/ 02 апреля 2020

execute принимает Runnable и затем вызывает его метод run в какой-то момент.

В своем вопросе вы продемонстрировали два способа передачи execute a Runnable:

  • передача объекта, который реализует Runnable:

    executorService.execute(new LongRunningTask());
    
  • передача лямбда-выражения, которое не принимает аргументов:

    executorService.execute(() -> new LongRunningTask());
    

В первом случае будет вызван new LongRunningTask().run(). Предположительно, это метод, который вы реализовали в //stuff happening here. Это код, который вы хотите запустить, верно?

Во втором случае лямбда-выражение равно run методу Runnable, поэтому будет запускаться new LongRunningTask(). Обратите внимание, что это не вызывает run метод LongRunningMethod (код, который вы хотите выполнить). Это просто вызывает конструктор.

Если вы действительно хотите использовать лямбда-выражение (хотя я не вижу смысла), вы можете сделать:

executorService.execute(() -> new LongRunningTask().run());
2 голосов
/ 02 апреля 2020

Этот executorService.execute(() -> new LongRunningTask()); создаст новый объект Runnable с телом метода run как new LongRunningTask(), поэтому он просто создаст объект.

, поэтому executorService.execute(() -> new LongRunningTask()); равно этому

executorService.execute(new Runnable() {
    @Override
    public void run() { // this run method's body will be executed by the service
        new LongRunningTask(); // just create the object
    }
});

С другой стороны new LongRunningTask() является самим исполняемым файлом, и будет вызван его метод run, содержащий фактический исполняемый код.

Он может быть дополнительно оптимизирован с помощью ссылки на метод как

executorService.execute(LongRunningTask::new);
...