一,FutureTask概述
- FutureTask也可以用作闭锁.FutureTask实现了Future语义,表示一种抽象的可生成结果的计算.FutureTask表示的计算是通过Callable来实现的,相当于一种可生成结果的Runnable,并且可以处于以下3种状态:等待运行,正在运行和运行完成.
- Future.get的行为取决于任务的状态.如果任务已经完成,那么get会立即返回结果,否则get将阻塞直到任务进入完成状态,然后返回结果或者抛出异常
二,Callable, Future, FutureTask的关系
- Callable
- Callable 接口类似于 Runnable,两者都是为那些其实例可能被另一个线程执行的类设计的。但是 Runnable 不会返回结果,并且无法抛出经过检查的异常。
- Callable是对任务的一种更好的抽象
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
- Future
- Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并获取计算的结果。计算完成后只能使用 get 方法来获取结果,如有必要,计算完成前可以阻塞此方法。取消则由 cancel 方法来执行。还提供了其他方法,以确定任务是正常完成还是被取消了。一旦计算完成,就不能再取消计算。如果为了可取消性而使用 Future 但又不提供可用的结果,则可以声明 Future<?> 形式类型、并返回 null 作为底层任务的结果。
- Future表示一个任务的生命周期,并提供了响应的方法来判断是否已经完成或取消,以及获取任务的结果或者取消任务等.
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
- FutureTask
- 可取消的异步计算。利用开始和取消计算的方法、查询计算是否完成的方法和获取计算结果的方法,此类提供了对 Future 的基本实现。仅在计算完成时才能获取结果;如果计算尚未完成,则阻塞 get 方法。一旦计算完成,就不能再重新开始或取消计算。
- 可使用 FutureTask 包装 Callable 或 Runnable 对象。因为 FutureTask 实现了 Runnable,所以可将 FutureTask 提交给 Executor 执行。
- FutureTask的继承关系
三,一个小示例
public class Test {
public static void main(String[] args){
FutureAndCallableDemo demo = new FutureAndCallableDemo();
List<Callable<String>> tasks = new ArrayList<Callable<String>>();
for(int i=0; i<5; i++){
tasks.add(new Task());
}
List<String> results = demo.executeTask(tasks);
for(String result : results){
System.out.println(result);
}
}
}
class Task implements Callable<String>{
@Override
public String call() throws Exception {
return Thread.currentThread().getName()+" "+System.currentTimeMillis();
}
}
class FutureAndCallableDemo{
ExecutorService executor = Executors.newCachedThreadPool();
public List<String> executeTask(List<Callable<String>> tasks){
List<String> results = new ArrayList<String>();
for(Callable<String> task : tasks){
FutureTask<String> result = new FutureTask<String>(task);
Thread thread = new Thread(result);
thread.start();
try {
results.add(result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return results;
}
}
参考:
<<java编发编程实战>>
网友评论