基本概念
Future接口是一个泛型接口Future<V>,V是返回的结果类型。返回的是Callable的call方法执行的结果值。此接口方法如下:
boolean cancel (boolean mayInterruptIfRunning) 取消任务的执行。参数指定是否立即中断任务执行,或者等等任务结束
boolean isCancelled () 任务是否已经取消,任务正常完成前将其取消,则返回 true
boolean isDone () 任务是否已经完成。需要注意的是如果任务正常终止、异常或取消,都将返回true
V get () throws InterruptedException, ExecutionException 等待任务执行结束,然后获得V类型的结果。InterruptedException 线程被中断异常, ExecutionException任务执行异常,如果任务被取消,还会抛出CancellationException
V get (long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 同上面的get功能一样,多了设置超时时间。参数timeout指定超时时间,uint指定时间的单位,在枚举类TimeUnit中有相关的定义。如果计算超时,将抛出TimeoutException
使用心得
1. 当有异步任务处理时需要设置超时时间,利用方法 V get (long timeout, TimeUnit unit),如果在指定时间内没有获取值,可以根据需要进行相应的取消等处理。
ExecutorService executor = Executors.newSingleThreadExecutor();
FutureTask<String> future =
new FutureTask<String>(new Callable<String>() {//使用Callable接口作为构造参数
public String call() {
//真正的任务在这里执行,这里的返回值类型为String,可以为任意类型
}});
executor.execute(future);
//在这里可以做别的任何事情
try {
result = future.get(5000, TimeUnit.MILLISECONDS); //取得结果,同时设置超时执行时间为5秒。同样可以用future.get(),不设置执行超时时间取得结果
} catch (InterruptedException e) {
futureTask.cancel(true);
} catch (ExecutionException e) {
futureTask.cancel(true);
} catch (TimeoutException e) {
futureTask.cancel(true);
} finally {
executor.shutdown();
}
2. future接口的实现类有futureTask类,futureTask类结合callable接口使用,当我们把callable接口中的call方法交给线程执行时,我们可以继续做其他事情,futureTask类可以获取call方法返回值,它的作用就是控制Callable的call方法的执行过程。其核心思想:一个方法f,计算过程可能非常耗时,等待f返回,显然不明智。可以在调用f的时候,立马返回一个Future,可以通过Future这个数据结构去控制方法f的计算过程。
代码使用
可以使用Executor线程池结合future接口进行任务执行,也可以自己new 一个线程执行,代码如下:
package test;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class FutureCook {
public static void main(String[] args) throws InterruptedException, ExecutionException {
long startTime = System.currentTimeMillis();
// 第一步 网购厨具
Callable<Chuju> onlineShopping = new Callable<Chuju>() {
@Override
public Chuju call() throws Exception {
System.out.println("第一步:下单");
System.out.println("第一步:等待送货");
Thread.sleep(5000); // 模拟送货时间
System.out.println("第一步:快递送到");
return new Chuju();
}
};
FutureTask<Chuju> task = new FutureTask<Chuju>(onlineShopping);
new Thread(task).start();//自己启动线程执行任务,即执行call方法
// 第二步 去超市购买食材
Thread.sleep(2000); // 模拟购买食材时间
Shicai shicai = new Shicai();
System.out.println("第二步:食材到位");
// 第三步 用厨具烹饪食材
if (!task.isDone()) { // 联系快递员,询问是否到货
System.out.println("第三步:厨具还没到,心情好就等着(心情不好就调用cancel方法取消订单)");
}
Chuju chuju = task.get();
System.out.println("第三步:厨具到位,开始展现厨艺");
cook(chuju, shicai);
System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms");
}
// 用厨具烹饪食材
static void cook(Chuju chuju, Shicai shicai) {}
// 厨具类
static class Chuju {}
// 食材类
static class Shicai {}
}
ExecutorService executor = Executors.newSingleThreadExecutor();
FutureTask<String> future =
new FutureTask<String>(new Callable<String>() {//使用Callable接口作为构造参数
public String call() {
//真正的任务在这里执行,这里的返回值类型为String,可以为任意类型
}});
executor.execute(future); //使用线程池执行任务,即运行call方法
//在这里可以做别的任何事情
try {
result = future.get(5000, TimeUnit.MILLISECONDS); //取得结果,同时设置超时执行时间为5秒。同样可以用future.get(),不设置执行超时时间取得结果
} catch (InterruptedException e) {
futureTask.cancel(true);
} catch (ExecutionException e) {
futureTask.cancel(true);
} catch (TimeoutException e) {
futureTask.cancel(true);
} finally {
executor.shutdown();
}
参考:http://www.cnblogs.com/cz123/p/7693064.html
参考:https://blog.youkuaiyun.com/liutong123987/article/details/79377764