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
}
}
根据 JavaDocs,get()
方法在必要时等待计算完成,然后检索其结果。
如果您想在任务完成后获得结果,请使用 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);
这将在另一个线程上工作,当那个未来结束时它就会完成。
当我使用 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
}
}
根据 JavaDocs,get()
方法在必要时等待计算完成,然后检索其结果。
如果您想在任务完成后获得结果,请使用 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);
这将在另一个线程上工作,当那个未来结束时它就会完成。