public interface Future{
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}
Future的实现类FutureTask特点:回调函数done()方法,当一个任务执行结束后,会回调这个done()方法,我们可以在done()方法中调用FutureTask的get()方法来获得计算的结果。在其他时候get()会阻塞我的UI线程。
局限性: Future:主要是获取任务执行结果和对异步任务的控制。1、但是如果是批量任务的话,获取执行结果很麻烦。因为不知道哪一个任务先完成,得不停的遍历查询。2、也因为Future.get是阻塞方法,使用不当会造成线程浪费。
解决方法:
1、批量任务中查询已完成任务,可以使用completionService,它提供了一个take()阻塞方法,用来获取所有已完成的任务。
2、对于第二个问题,可以用 Google Guava 库所提供的 ListeningExecutorService 和 ListenableFuture 来解决。ListenableFuture可以允许注册回调方法(callbacks),在运算(多线程执行)完成的时候进行调用, 或者在运算(多线程执行)完成后立即执行。
Future 在高并发环境下有可能重复提交任务的,所以需要FutureTask阻止这种情况发生,保证只会执行一次。将FutureTask放入map之中,用键值对保存。
FutureTask是一个RunnableFuture,继承Runnable、future,所以FutureTask可以提交给 Executor执行也可以由调用线程直接执行FutureTask.run()方法。FutureTask的run()方法中又会调用Callable的call()方法。
那为什么FutureTask还要继承Runnable呢? Callable与Runnable:描述的都是抽象的计算任务。Runnable有局限性,虽然能将结果写入日志文件或者某个方式共享数据结构,但是不能返回一个值或者抛出异常;Callable是对Runnable局限性的弥补。
public interface RunnableFuture extends Runnable, Future{
}
private volatile intstate;
private static final intNEW=0;新建
private static final intCOMPLETING=1;执行中
private static final intNORMAL=2;正常
private static final intEXCEPTIONAL=3;异常
private static final intCANCELLED=4;取消
private static final intINTERRUPTING=5;中断中
private static final intINTERRUPTED=6;被中断
state的状态变化可以有四种方式
NEW->COMPLETING->NORMAL 正常完成的流程
NEW->COMPLETING->EXCEPTIONAL 出现异常的流程
NEW->CANCELED 被取消
NEW->INTERRUNPING->INTERRRUNPTED 被中断