Java 未来:如何在执行异步调用时解锁主线程

Java Future : How to unblock Main thread while executing Aysnc call

当我使用 ExecutorService 进行异步调用时,它 returns 未来对象。基于它的布尔值 returns,我必须记录异步调用的状态。

但是当我尝试从 future 对象调用方法 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
    }

}

根据 JavaDocsget() 方法在必要时等待计算完成,然后检索其结果。

如果您想在任务完成后获得结果,请使用 isDone() 函数,如果任务完成(正常、异常等),则 returns true。然后调用 get()

此外,您可以使用 get(long timeout, TimeUnit unit) 函数只等待给定的时间段。在这种情况下,如果超时或任务已完成,主线程将自动 "unblocked"。

如果您需要在异步任务 运行 时在主线程中执行代码,您将需要重新设计 asyncCall 方法以使其成为 return 未来。

一个例子:

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

    return hystrixCommand.queue(); 
}

这样,main 方法就何时进行调用 block/wait:

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();
}

futures 的好处是能够在答案到达之前释放线程。 所以我建议你使用 Future 实现,比如 CompletableFuture:

final ExecutorService executorService = Executors.newFixedThreadPool(10);

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

这将在另一个线程上工作,当那个未来结束时它就会完成。