Future类提供了方法来检查异步调用是否完成、等待异步调用完成并获取异步调用返回结果。get()方法可以对线程进行阻塞,直到异步调用完成并返回结果。cancel()方法可以取消异步方法的执行。
Future是一个接口,定义了异步线程的返回结果的获取方法,以及异步线程执行的取消方法。下面看源码:
boolean cancel(boolean mayInterruptIfRunning);
尝试取消此任务的执行。如果任务已完成、已取消或由于其他原因无法取消,则此尝试将失败。如果成功,并且在调用cancel时此任务尚未启动,则此任务不应运行。如果任务已经启动,则mayInterruptIfRunning参数确定执行此任务的线程是否应该中断以尝试停止任务。
此方法返回后,对isDone的后续调用将始终返回true。如果此方法返回true,则对isCancelled的后续调用将始终返回true。
V get() throws InterruptedException, ExecutionException;
如果需要,等待计算完成,然后检索其结果
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
如果需要,最多等待给定时间以完成计算,然后检索其结果(如果可用)。
FutureTask类实现了Future接口定义的方法。FutureTask可以用于包装Callable或Runnable类,因为FutureTask实现了Runnable,所以Future任务可以提交给Executor执行。除了用作独立类之外,该类还提供了受保护的功能,这些功能在创建自定义任务类时可能很有用。
FutureTask构造函数中可接收Runnable类或Callable类。然后可以调用FutureTask的run方法。如此调用的话,Runnable或Callable中任务就在同一个线程里调用了,属于同步调用了。如下示例:
public static void main(String[] args) throws InterruptedException, ExecutionException {
FutureTask<Integer> futureTask=new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() {
System.out.println(Thread.currentThread().getName());
try{
Thread.sleep(5000);
System.out.println(666);
}catch (Exception e){
}
return RandomUtils.nextInt();
}
});
futureTask.run();
System.out.println(Thread.currentThread().getName());
Integer integer = futureTask.get();
System.out.println(123);
}
返回值如下,且是同步运行:
FutureTask对象也可以交付给另外一个线程或线程池执行,如下:
//托管给线程池处理
Future<?> futureResult = Executors.newCachedThreadPool().submit(future);
//托管给单独线程处理
new Thread(future).start();
此时FutureTask中任务与主线程就是异步执行了。通过get()方法可以阻塞主线程,等待异步线程的返回结果,通过cancel()方法可以取消异步线程执行。一般应用场景为主线程执行任务过多时,采用异步方式同时执行,并在最后等待异步都执行完后,统一结束主线程。