Почему метод этого будущего блокирует основной поток? - PullRequest
1 голос
/ 24 января 2020
ExecutorService executor = Executors.newFixedThreadPool(2);

Future<Integer> calculate(Integer input) {
    return executor.submit(() -> {
        Thread.sleep(3000);
        return input * input;
    });
}

public static void main(String []args) throws Exception {
    Main m = new Main();
    System.out.println(m.calculate(5).get());
    System.out.println("Main");

Мы отправляем Callable в Executor с двумя потоками, но когда я говорю m.calculate(5).get(), он блокирует основной поток. Итак, я не могу понять, когда и почему я должен использовать Future, если он блокирует основной поток и не работает асинхронно?

Ответы [ 2 ]

7 голосов
/ 24 января 2020

Если вы заглянете в документацию Future::get, там написано: " Дождется завершения вычисления и при необходимости получит его результат. " Вызывая этот метод, вы соглашаетесь дождаться результата в основной теме.

Вы можете проверить, завершилось ли Future, вызвав Future::isDone, который возвращает логическое значение.

В вашем сценарии его можно использовать следующим образом:

public static void main(String []args) throws Exception {
    Main m = new Main();
    Future<Integer> futureInt = m.calculate(5);
    // do some other asynchronous task or something in main thread while futureInt is doing its calculations
    // and then call Future::get
    int result = futureInt.get();

См .: до c

5 голосов
/ 24 января 2020

Future действительно очень ограниченная абстракция, в более реалистичных c случаях вы должны использовать CompletableFuture вместо этого. Future довольно старый класс (начиная с java 1,5, я полагаю), поэтому понимание отрасли постепенно развивается в области параллельного программирования,

Тем не менее, он все еще может быть полезен сам по себе.

Что если вместо того, чтобы порождать одно будущее и немедленно вызывать get, мы бы хотели создать много задач и сохранить результат в некотором списке:

List<Future<Integer>> futures = new ArrayList<>(10);
for(int i = 0 ; i< 10; i++) {
   futures.add(calculate(<some_integer>));
}
// at this point all futures are running concurrently
for(int i = 0 ; i < 10; i++) {
   futures.get(i).get(); // will either return immediately or we'll block the main thread but the point is that all the calculations will run concurrently
}
...