写了这么多终于来到了future 这里, 这个题目真的和它很贴切 , 我们之前在线程池已经多次见到这个对象了 , 这一篇我们重点看一看他
一 . Future 是什么
1.3 Future Task 简述
作用 : future 可以用于异步获取多线程任务结果 , Callable 用于产生结果,Future 用于获取结果
流程 : 流程类似于叫好等餐 , 等餐是花费时间的过程,但是不妨碍我们叫号
- 当 Future 进行 submit 开始 , 业务处理已经在多线程中开始 , 而 Get 即从多线程中获取数据
- 当 Get 获取时业务还未处理完 , 当前线程会阻塞 , 直到业务处理完成 . 所以需要注意 future 的任务安排
使用 future 会有以下效果:
- 1 启动多线程任务
- 2 处理其他事情
- 3 收集多线程任务结果
Future 对应的方法 :
- cancel(boolean) : 取消操作
- get() : 获取结果
- get(long,TimeUtil) : 指定时间获取
- isCancelled() : 该任务是否在完成之前被取消
- isDone() :判断是否有结果
Future 接口的作用就是先生成一个 Future 对象 ,将具体的运行放入future 对象中 ,最终通过future 对象的 get 方法来获取最终的结果
1.2 Future Task
FutureTask 表示一个可以取消的异步运算 ,提供了Future 完整的流程
- 它有启动和取消运算、查询运算是否完成和取回运算结果等方法。
- 只有当运算完成的时候结果才能取回,如果运算尚未完成 get 方法将会阻塞
我们关注一下以下源码细节点 :
1 | java复制代码 |
二 . Future 使用
Future 使用其实比较简单 , 发起等待即可 , 但是注意Future 是会阻塞主线程的
1 | java复制代码public class FutureService extends AbstractService implements ApplicationRunner, Callable<String> { |
三 . Future 问答
按照线程池最常见的用法 , 我们通过 executor.submit 时会返回一个 Future 对象 ,然后通过 Future 对象获取
First : 我们以这个方法去推理
ExecutorService executor = Executors.newFixedThreadPool(1);
Future future = executor.submit(A Callable Object);
问题一 : Future 底层基于什么 ?
- Step 1 : 当通过 submit 调用的时候 , 底层会调用 :
return new FutureTask<T>(runnable, value);
- Step 2 : 在外层会被提升为父类 RunnableFuture , 在返回的时候又会被提成 Future
RunnableFuture<T> ftask = newTaskFor(task, result);
总结 : 所以 , 底层的实现类主要可以看成 FutureTask , 而task 实际上可以算 Runnable 的实现类
问题二 : Future 怎么运行 ?
Future 运行主要基于 run()
- 通过调用 callable.call() 完成
- 如果call执行成功,则通过set方法保存结果 ,将 result 保存到 outcome;
- 如果call执行有异常,则通过setException保存异常;
问题三 : future 回调基于什么 – get(long,TimeUtil) ?
通过调用 report(s) 完成调用
问题四 : future 阻塞的方式 ?
当判断未完成时 , 会调用 awaitDone 等待 , 具体的逻辑以后分析
1 | java复制代码if (s <= COMPLETING){ |
awaitDone 中主要做了以下几件事 :
- 如果主线程被中断,则抛出中断异常;
- 判断FutureTask当前的state,如果大于COMPLETING,说明任务已经执行完成,则直接返回;
- 如果当前state等于COMPLETING,说明任务已经执行完,这时主线程只需通过yield方法让出cpu资源,等待state变成NORMAL;
- 通过WaitNode类封装当前线程,并通过UNSAFE添加到waiters链表;
- 最终通过LockSupport的park或parkNanos挂起线程;
问题五 : future 怎么取消 ?
- cancel(boolean mayInterruptIfRunning) 中 t.interrupt()
- 并且 UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); 修改状态
问题六 : future 怎么判断取消和结果 isCancelled – isDone ?
return state >= CANCELLED;
四 . Future 与 Callable
这个需要从 ExecutorService.submit() 来看 , ExecutorService 有2个主要的 submit 方法 , 不论是 Callable , 还是Runnable , 通过返回值就不难发现 ,其最终都变成了一个 Future
1 | java复制代码<T> Future<T> submit(Callable<T> task); |
五 . 衍生用法 ScheduledFutureTask
1 | java复制代码// ScheduledFutureTask 简介 |
核心代码参考线程池这篇文档
致谢 :
本文转载自: 掘金