1. FutureTask概述
FutureTask的应用场景主要是一个线程需要等待另一个线程的时候可以使用,FutureTask的get()方法会使当前线程阻塞,直到目标线程完成任务返回结果,才会继续往下执行。FutureTask最大的特点就是支持取消任务。
根据FutureTask的run执行的状态,可以分为三种情况:
- 未启动状态:FutureTask.run()方法执行之前,处于未启动状态
- 已启动状态:FutureTask.run()方法已经执行了,但是任务还未执行完
- 已完成状态:FutureTask.run()方法已经执行完成
如下图所示:
针对run()方法的三种状态,FutureTask.cancel()方法也对应三种取消时间:
- 未启动状态:执行FutureTask.cancel()方法将此任务永远不会执行
- 已启动状态:执行FutureTask.cancel(true)方法将以中断线程的方式来阻止任务继续进行,如果执行FutureTask.cancel(false)将不会对正在执行任务的线程有任何影响
- 已完成状态:执行FutureTask.cancel(…)方法将返回false
针对run()方法的三种状态,FutureTask.get()方法也对应三种情况:
- 未启动状态:进入阻塞状态
- 已启动状态:进入阻塞状态
- 已完成状态:返回结果或抛出异常
如下图所示:
2. FutureTask应用
FutureTask除了实现Future接口外,还实现了Runnable接口。因此,FutureTask可以交给线程池执行,也可以由调用的线程直接执行。此外,FutureTask的获取也可以通过ExexcutorService.submit()方法返回的FutureTask对象。下面举一个使用线程池执行的例子:
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class TestFutureTask {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Runnable runnable = new Runnable() {
@Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println("第" + i + "个子任务正在执行");
}
}
};
FutureTask futureTask = new FutureTask(runnable,"task completed");
ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.execute(futureTask);
System.out.println(futureTask.get());
System.out.println("end");
}
}
输出结果:
第0个子任务正在执行
第1个子任务正在执行
第2个子任务正在执行
第3个子任务正在执行
第4个子任务正在执行
第5个子任务正在执行
第6个子任务正在执行
第7个子任务正在执行
第8个子任务正在执行
第9个子任务正在执行
task completed
end
参考文章:FutureTask基本操作总结