4.1.5 timed get - 超时获取
- 必要时最多等待给定时间以完成任务,然后获取其结果(若有)
- 抛CancellationException 如果任务被取消
抛 ExecutionException 如果任务抛了异常
抛InterruptedException 如果当前线程在等待时被中断
抛TimeoutException 如果等待超时了
两个get()方法都是阻塞的,若被调用时,任务还没有执行完,则调用get()方法的线程会阻塞,直到任务执行完才会被唤醒。所以future.get()会阻塞当前调用线程。
阻塞异步线程
阻塞主线程
5 RunnableFuture
Java6 时提供的持有 Runnable 性质的 Future。
成功执行run方法导致Future的完成,并允许访问其结果。
RunnableFuture接口比较简单,就是继承了 Runnable 和 Future 接口。只提供一个run方法
创建任务有两种方式
- 无返回值的 Runnable
- 有返回值的 Callable
但这样的设计,对于其他 API 来说并不方便,没法统一接口。
所以铺垫了这么多,主角 FutureTask 来了!
6 FutureTask
Future是个接口,FutureTask 才是个实实在在的工具类,是线程运行的具体任务。
实现了 RunnableFuture 接口,即实现了 Runnnable 接口,即FutureTask 本身就是个 Runnnable。也表明了 FutureTask 实现了 Future,具备对任务进行管理的功能。
6.1 属性
6.1.1 运行状态
最初为NEW
。 运行状态仅在set,setException和cancel方法中转换为最终状态。
在完成期间,状态可能会呈现COMPLETING(正在设置结果时)或INTERRUPTING(仅在中断运行任务去满足cancel(true)时)的瞬态值。
从这些中间状态到最终状态的转换使用更加低价的有序/惰性写入,因为值是唯一的,无法进一步修改。
常量字段定义:
- NEW
线程任务创建,开始状态 - COMPLETING
任务执行中,正在运行状态 - NORMAL
任务执行结束 - EXCEPTIONAL
任务异常 - CANCELLED
任务取消成功 - INTERRUPTING
任务正在被打断中 - INTERRUPTED = 6
任务被打断成功
可能的状态转换
- NEW -> COMPLETING -> NORMAL
- NEW -> COMPLETING -> EXCEPTIONAL
- NEW -> CANCELLED
- NEW -> INTERRUPTING -> INTERRUPTED
6.1.2 其他属性
- 组合的 callable,这样就具备了转化 Callable 和 Runnable 的功能
- 从ge()返回或抛异常的结果,非volatile,受state的读/写保护
- 运行 callable 的线程; 在run()期间进行CAS
- 记录调用 get 方法时被等待的线程 - 栈形式
- Callable 是作为 FutureTask 的属性之一,接着我们看下 FutureTask 的构造器,看看两者是如何转化的。