FutureTask

Future接口和实现Future接口的FutureTask类,代表异步计算的结果.

简介

在Java中一般通过继承Thread类或者实现Runnable接口这两种方式来创建多线程,但是这两种方式都有个缺陷,就是不能在执行完成后获取执行的结果,因此Java 1.5之后提供了Callable和Future接口,通过它们就可以在任务执行完毕之后得到任务的执行结果。

Callable接口

对于需要执行的任务需要实现Callable接口,Callable接口定义如下:

1
2
3
4
5
6
7
8
9
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;
}

可以看到Callable是个泛型接口,泛型V就是要call()方法返回的类型。Callable接口和Runnable接口很像,都可以被另外一个线程执行,但是正如前面所说的,Runnable不会返回数据也不能抛出异常。

Future 接口

Future接口代表异步计算的结果,通过Future接口提供的方法可以查看异步计算是否执行完成,或者等待执行结果并获取执行结果,同时还可以取消执行。Future接口的定义如下:

1
2
3
4
5
6
7
8
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;
}
  • cancel():cancel()方法用来取消异步任务的执行。如果异步任务已经完成或者已经被取消,或者由于某些原因不能取消,则会返回false。如果任务还没有被执行,则会返回true并且异步任务不会被执行。如果任务已经开始执行了但是还没有执行完成,若mayInterruptIfRunning为true,则会立即中断执行任务的线程并返回true,若mayInterruptIfRunning为false,则会返回true且不会中断任务执行线程。
  • isCanceled():判断任务是否被取消,如果任务在结束(正常执行结束或者执行异常结束)前被取消则返回true,否则返回false。
  • isDone():判断任务是否已经完成,如果完成则返回true,否则返回false。需要注意的是:任务执行过程中发生异常、任务被取消也属于任务已完成,也会返回true。
  • get():获取任务执行结果,如果任务还没完成则会阻塞等待直到任务执行完成。如果任务被取消则会抛出CancellationException异常,如果任务执行过程发生异常则会抛出ExecutionException异常,如果阻塞等待过程中被中断则会抛出InterruptedException异常。
  • get(long timeout,Timeunit unit):带超时时间的get()版本,如果阻塞等待过程中超时则会抛出TimeoutException异常。
FutureTask

FutureTask 继承了RunnableFuture接口,RunnableFuture接口继承了Runnable接口和Future接口

所以FutureTask既能当做一个Runnable直接被Thread执行,也能作为Future用来得到Callable的计算结果。(目前我觉得是两个都是必须的,又作为runnable,又作为返回结果,都是必须的)

当作为Runnable时,有三种状态

  • 未启动 FutureTask.run()方法还没有执行之前.
  • 已启动 FutureTask.run()方法执行过程中
  • 已完成 FutureTask.run()方法执行结束后

FutureTask主要使用get()和cancle()两个方法.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class FutureCallableDemo {
public static class RealData implements Callable<String>
{
private String para;
public RealData(String para)
{
this.para=para;
}
@Override
public String call() throws Exception {
StringBuffer sb =new StringBuffer();
for(int i=0;i<10;i++)
{
sb.append(para);
Thread.sleep(100);
}
return sb.toString();
}// 上述代码实现了Callable接口,它的call()方法会构造我们需要的真实数据并返回,这里用sleep进行模拟.
}
public static class FutureMain
{
public static void main(String[] args) throws Exception
{
//构造FutureTask
RealData realData =new RealData("a");
FutureTask<String> future = new FutureTask<String>(realData);//1111111
ExecutorService es = Executors.newFixedThreadPool(1);
// 执行FutureTask
es.submit(future); //作为执行!!!!!!!!!!!!!!!!!!!
//写了111那句后,就必须submit future了.
Thread.sleep(300);// 模拟做一些额外的事情
System.out.println(future.get());// 在需要的时候通过get()方法获得需要的数据.,也作为返回!!!!!!!!!!!!!!!!!
}
}
}
//既作为执行,也作为返回.