Будущее Java: как разблокировать основной поток при выполнении вызова Aysnc - PullRequest
1 голос
/ 11 апреля 2019

Когда я делаю асинхронный вызов с использованием ExecutorService, он возвращает Future Object. Основываясь на булевом значении, которое он возвращает, я должен записать состояние асинхронного вызова.

Но когда я пытаюсь вызвать метод get из будущего объекта, он блокирует выполнение основного потока.

Можно ли разблокировать выполнение основного потока?

public class FutureExample {

    static HystrixCommand<Boolean> hystrixCommand;

    public FutureExample(HystrixCommand<Boolean> hystrixCommand){
        FutureExample.hystrixCommand = hystrixCommand;
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException {


        Boolean something = asyncCall();

        if(something) {
            System.out.println("Future task is done");
        }

        System.out.println("Don't wait for async call");

    }

    private static Boolean asyncCall() throws InterruptedException, ExecutionException {

        Future<Boolean> response = hystrixCommand.queue(); // Aysnc Call to remote server

        return response.get(); //this is blocking main thread
    }

}

Ответы [ 3 ]

4 голосов
/ 11 апреля 2019

Хорошая вещь о фьючерсах - возможность выпускать темы, пока не придет ответ. Поэтому я рекомендую вам использовать реализацию Future, например, CompletableFuture:

final ExecutorService executorService = Executors.newFixedThreadPool(10);

CompletableFuture.supplyAsync(() -> {
    try {
        return hystrixCommand.queue();
    } catch (Exception e) {
        return false;
    }
}, executorService);

Это будет работать в другом потоке, и когда это будущее закончится, оно будет сделано.

1 голос
/ 11 апреля 2019

Если вам нужно выполнить код в главном потоке во время выполнения асинхронной задачи, вам нужно будет изменить метод asyncCall, чтобы он вместо этого возвращал будущее.

Пример:

private static Future<Boolean> asyncCall() 
      throws InterruptedException, ExecutionException {

    return hystrixCommand.queue(); 
}

Таким образом, основной метод выполняет вызов относительно того, когда блокировать / ждать:

public static void main(String[] args) 
     throws InterruptedException, ExecutionException {

    Future<Boolean> something = asyncCall();

    //do something while async call is running

    //to check whether it's done running:
    if(something.isDone()) {
        System.out.println("Future task is done");
    }

    //when you're finally ready to wait:
    System.out.println("Waiting for async call to finish");
    Boolean result = something.get();
}
1 голос
/ 11 апреля 2019

Согласно JavaDocs , метод get() ожидает, если необходимо, чтобы вычисление завершилось, и затем извлекает его результат.

Если вы хотите получить результат после завершения задачи, используйте функцию isDone(), которая возвращает true, если задача выполнена (обычно, исключительно и т. д.).И затем вызовите get().

Кроме того, вы можете использовать функцию get(long timeout, TimeUnit unit) для ожидания только в течение заданного периода времени.В этом случае основной поток автоматически разблокируется, если время истекло или задание завершено.

...