主打一手结果导向;
一、背景
在系统中,异步执行任务,是很常见的功能逻辑,但是在不同的场景中,又存在很多细节差异;
有的任务只强调「执行过程」,并不需要追溯任务自身的「执行结果」,这里并不是指对系统和业务产生的效果,比如定时任务、消息队列等场景;
但是有些任务即强调「执行过程」,又需要追溯任务自身的「执行结果」,在流程中依赖某个异步结果,判断流程是否中断,比如「并行」处理;
【串行处理】整个流程按照逻辑逐步推进,如果出现异常会导致流程中断;
【并行处理】主流程按照逻辑逐步推进,其他「异步」交互的流程执行完毕后,将结果返回到主流程,如果「异步」流程异常,会影响部分结果;
此前在《「订单」业务》的内容中,聊过关于「串行」和「并行」的应用对比,即在订单详情的加载过程中,通过「并行」的方式读取:商品、商户、订单、用户等信息,提升接口的响应时间;
二、Future接口
1、入门案例
异步是对流程的解耦,但是有的流程中又依赖异步执行的最终结果,此时就可以使用「Future」接口来达到该目的,先来看一个简单的入门案例;
public class ServerTask implements Callable<Integer> {
@Override
public Integer call() throws Exception {
Thread.sleep(2000);
return 3;
}
}
public class FutureBase01 {
public static void main(String[] args) throws Exception {
TimeInterval timer = DateUtil.timer();
// 线程池
ExecutorService executor = Executors.newFixedThreadPool(3);
// 批量任务
List<ServerTask> serverTasks = new ArrayList<>() ;
for (int i=0;i<3;i++){
serverTasks.add(new ServerTask());
}
List<Future<Integer>> taskResList = executor.invokeAll(serverTasks) ;
// 结果输出
for (Future<Integer> intFuture:taskResList){
System.out.println(intFuture.get());
}
// 耗时统计
System.out.println("timer...interval = "+timer.interval());
}
}
复制代码
这里模拟一个场景,以线程池批量执行异步任务,在任务内线程休眠2秒,以并行的方式最终获取全部结果,只耗时2秒多一点,如果串行的话耗时肯定超过6秒;
2、Future接口
Future表示异步计算的结果,提供了用于检查计算是否完成、等待计算完成、以及检索计算结果的方法。
【核心方法】
get()
:等待任务完成,获取执行结果,如果任务取消会抛出异常;get(long timeout, TimeUnit unit)
:指定等待任务完成的时间,等待超时会抛出异常;isDone()
:判断任务是否完成;isCancelled()
:判断任务是否被取消;cancel(boolean mayInterruptIfRunning)
:尝试取消此任务的执行,如果任务已经完成、已经取消或由于其他原因无法取消,则此尝试将失败;
【基础用法】
public class FutureBase02 {
public static void main(String[] args) throws Exception {
// 线程池执行任务
ExecutorService executor = Executors.newFixedThreadPool(3);
FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(3000);
return "task...OK";
}
}) ;
executor.execute(futureTask);
// 任务信息获取
System.out.println("是否完成:"+futureTask.isDone());
System.out.println("是否取消:"+futureTask.isCancelled());
System.out.println("获取结果:"+futureTask.get());
System.out.println("尝试取消:"+futureTask.cancel(Boolean.TRUE));
}
}
复制代码
【FutureTask】
Future接口的基本实现类,提供了计算的启动和取消、查询计算是否完成以及检索计算结果的方法;
在「FutureTask」类中,可以看到线程异步执行任务时,其中的核心状态转换,以及最终结果写出的方式;
虽然「Future」从设计上,实现了异步计算的结果获取,但是通过上面的案例也可以发现