本文为读书笔记
可参考:FutureTask jdk8实现
JKD1.8不再依赖AQS来实现,而是用的CAS+state
1. FutureTask简介
Future接口和实现Future接口的FutureTask类,代表异步计算的结果。
此任务的运行状态,最初是新的。运行状态只有在方法集中才会过渡到终端状态, setException和cancel。在完成期间,state可能会承担暂态值的完成(而结果正在被设置)或中断(仅在中断跑步者以满足a时)取消(真))。从这些中间过渡到最终状态使用更便宜的有序/惰性写,因为值是唯一的无法进一步修改。
- Possible state transitions:
- NEW -> COMPLETING -> NORMAL
- NEW -> COMPLETING -> EXCEPTIONAL
- NEW -> CANCELLED
- NEW -> INTERRUPTING -> INTERRUPTED
//注意关键字state
private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
根据FutureTask.run()方法被执行的时机,FutureTask可以处于下面3种状态。
1)未启动。FutureTask.run()方法还没有被执行之前,FutureTask处于未启动状态。当创建一个FutureTask,且没有执行FutureTask.run()方法之前,这个FutureTask处于未启动状态。
2)已启动。FutureTask.run()方法被执行的过程中,FutureTask处于已启动状态。
3)已完成。FutureTask.run()方法执行完后正常结束,或被取消(FutureTask.cancel(…)),或执行FutureTask.run()方法时抛出异常而异常结束,FutureTask处于已完成状态。
状态跃迁图
2. FutureTask的使用
可以把FutureTask交给Executor执行;也可以通过ExecutorService.submit(…)方法返回一个FutureTask,然后执行FutureTask.get()方法或FutureTask.cancel(…)方法。除此以外,还可以单独使用FutureTask。
当一个线程需要等待另一个线程把某个任务执行完后它才能继续执行,此时可以使用FutureTask。
假设有多个线程执行若干任务,每个任务最多只能被执行一次。当多个线程试图同时执行同一个任务时,只允许一个线程执行任务,其他线程需要等待这个任务执行完后才能继续执行。
部分核心方法:
3. FutureTask的实现(JKD1.8不再依赖AQS来实现)
文章应该是1.8以前:
FutureTask的 实 现 基 于AbstractQueuedSynchronizer(以 下 简 称 为AQS)。
设计示意图:
4. 使用举例
public static void main(String[] args) {
Callable<Integer> call = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return 1;
}
};
FutureTask<Integer> task = new FutureTask<>(call);
//交给Thread执行
Thread thread = new Thread(task);
thread.start();
Integer result = null;
try {
result = task.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
System.out.println("结果为:" + result);
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
C c = new C();
FutureTask futureTask = new FutureTask<>(c);
executorService.execute(futureTask);
System.out.println(futureTask.get());
executorService.shutdownNow();
}
class C implements Callable {
@Override
public Object call() throws Exception {
return 1;
}
}
或者
Future submit = executorService.submit(c);
System.out.println(submit.get());
executorService.shutdownNow();