Java 并发编程学习(六):FutureTask与Future
Future基本介绍
在上一篇文章中,我们用到了Future,Future具体可以用来做什么呢?要搞明白这个问题,首先要知道Future从哪儿来。下面是一个简单的例子:
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(1);
// 创建一个runnable实例
Runnable r = () -> {
System.out.println("Runnable类型的任务在执行");
};
// 创建一个Callable实例
Callable<String> c = () -> {
System.out.println("Callable类型的任务在执行");
return "finish";
};
// 提交任务
Future<?> rf = service.submit(r);
Future<String> cf = service.submit(c);
// 1、获取任务的返回值
String resultOfCallable = cf.get();
// 2、判断任务是否执行结束
if (cf.isDone()) {
}
// 3、取消任务的执行
cf.cancel(true);
// 4、判断任务是否取消了
if (cf.isCancelled()) {
}
// 关闭线程池
service.shutdown();
}
}
从代码可以看到,向线程池提交一个任务(Runnable、Callable实例)的时候,返回一个Future对象。然后通过这个Future对象可以获知任务的状态(是否完成、获取任务返回值),或者使用Future对象可以干涉任务的执行(比如取消任务),由此可见,Future是用于管理任务的,没有任务就没有Future。
FutureTask基本介绍
FutureTask可以用来干什么?FutureTask和Future是什么关系?通过观察FutureTask类的继承关系,我们可以窥探一二。
从继承结构可以看出来,FutureTask既可以当作一个Runnable又可以当一个Future,什么意思?举个例子:
import java.util.concurrent.*;
public class Main {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService service = Executors.newFixedThreadPool(1);
// 创建一个task
Callable<String> c = () -> {
System.out.println("[" + Thread.currentThread().getName() + "] " + "Callable task finished");
return "finish";
};
// 创建一个FutureTask对象,并将其作为Runnable提交到线程池
FutureTask<String> task = new FutureTask<>(c);
service.submit(task);
// 使用FutureTask获取任务执行结果
String result = task.get();
System.out.println("[" + Thread.currentThread().getName() + "] " +result);
// 关闭线程池
service.shutdown();
}
}
运行结果:
在向线程池提交任务时,直接将FutureTask对象作为参数,因为从继承关系可以看出来FutureTask可以做为Runnable使用。在获取任务执行结果时,可以直接通过FutureTask对象的get()方法来获取,因为FutureTask类实现了Future接口。