Runnable 是一个接口,在它里面只声明了一个 run()方法,由于 run()方法返 回值为 void 类型,所以在执行完任务之后无法返回任何结果。
Callable 位于 java.util.concurrent 包下,它也是一个接口,在它里面也只声明 了一个方法,只不过这个方法叫做 call(),这是一个泛型接口,call()函数返回的 类型就是传递进来的 V 类型。
Future 就是对于具体的 Runnable 或者 Callable 任务的执行结果进行取消、查 询是否完成、获取结果。必要时可以通过 get 方法获取执行结果,该方法会阻塞 直到任务返回结果。

Future接口用于获取异步计算的结果,可通过get()获取结果、cancel()取消、isDone()判断是否完成等操作。
V get(): 获取结果,若无结果会阻塞至异步计算完成
V get(long timeOut, TimeUnit unit):获取结果,超时返回null
boolean isDone():执行结束(完成/取消/异常)返回true
boolean isCancelled():任务完成前被取消返回true
boolean cancel(boolean mayInterruptRunning):取消任务,未开始或已完成返回false,参数表示是否中断执行中的线程
因为 Future 只是一个接口,所以是无法直接用来创建对象使用的,因此就 有了下面的 FutureTask。

FutureTask 类实现了 RunnableFuture 接口,RunnableFuture 继承了 Runnable 接口和 Future 接口,而 FutureTask 实现了 RunnableFuture 接口。所以它既可以 作为 Runnable 被线程执行,又可以作为 Future 得到 Callable 的返回值。

因此我们通过一个线程运行 Callable,但是 Thread 不支持构造方法中传递 Callable 的实例,所以我们需要通过 FutureTask 把一个 Callable 包装成 Runnable, 然后再通过这个 FutureTask 拿到 Callable 运行后的返回值。 要 new 一个 FutureTask 的实例,有两种方法:

示例:
/**
*类说明:演示Future等的使用
*/
public class UseFuture {
/*实现Callable接口,允许有返回值*/
private static class UseCallableimplements Callable{
private int sum;
@Override
public Integer call()throws Exception {
System.out.println("Callable子线程开始计算!");
// Thread.sleep(1000);
for(int i=0 ;i<5000;i++){
if(Thread.currentThread().isInterrupted()) {
System.out.println("Callable子线程计算任务中断!");
return null;
}
sum=sum+i;
System.out.println("sum="+sum);
}
System.out.println("Callable子线程计算结束!结果为: "+sum);
return sum;
}
}
public static void main(String[] args)
throws InterruptedException, ExecutionException {
UseCallable useCallable =new UseCallable();
//包装
FutureTask futureTask =new FutureTask<>(useCallable);
Random r =new Random();
new Thread(futureTask).start();
Thread.sleep(1);
if(r.nextInt(100)>50){
System.out.println("Get UseCallable result = "+futureTask.get());
}else{
System.out.println("Cancel................. ");
futureTask.cancel(true);
}
}
}
网友评论