Future和FutureTask
1,Future
java.util.concurrent.Future接口提供了线程不会因为等待返回结果而阻塞的能力。
设想一个生活场景,用于需要申请车牌,它在提交了申请之后,与长达数小时的等待过程,在这个过程里,用户可以做自己想做的其他事情,而无需一直在窗口等待车牌制作完成。
在这个过程中,用于可以放弃领取,也可以一直在窗口等待,也可以在窗口看看,能拿走则拿走,不行就在等一会去做别的事。
Future模式就是提供了这样的能力,让线程可以灵活的确定自己在何时取得结果。
2,FutureTask
java.util.concurrent.FutureTask是Future接口在concurrency包中的默认实现,它的主要用途之一是为了AbstractExecutorService提供任务支持,交由AbstractExecutorService执行的任务会被包装成一个FutureTask,以提供延时获取返回值的能力。
FutureTask间接继承自Future接口和Runnable接口,所以,它同时具备执行任务和获取结果两种能力,FutureTask把实现委托给了其内部的AQS来实现。
AQS是一个抽象队列同步器,内部维护了一个等待队列和等待状态。
3,Sync的四种状态
Sync设计了四种状态,可见,Sync的实现也采用了状态机模式。
READY:任务准备完毕,可以运行
RUNNING:任务正在运行
RAN:任务运行完毕
CANCELLED:任务取消
4,Sync的运行
innerRun的实现很简单:
1) 检查任务是否为READY状态,如果不是,那么认为已经被调用过了,直接返回。
2) 设置任务为RUNNING状态,表示当前Sync申领了该任务,如果该任务没有被其它线程修改,那么执行该任务。
3) 如果其它线程修改了该任务额状态,例如RAN或者CANCELLED,那么中断执行。
5,Sync的取消
innerCancel方法的关键点有几处:
1) 只有READY或者RUN状态的任务才能取消。
2) 根据参数来决定是否要中断线程阻塞。
6,Sync获取数据
innerGet方法用于异步获取数据,其逻辑实现如下:
1) 如果任务已经执行完成了,那么直接返回结果。
2) 如果任务尚未完成,那么等待任务完成后返回结果。
通过对innerGet逻辑实现的分析,可以得出:
1) 线程访问innerGet时,如果任务不是RAN或者CANCELLED状态,那么线程会被阻塞。
2) result来自于innerRun()里callable的返回值
7,Sync和AQS
在运行/取消方法里,调用了tryReleaseShared,在取值方法里,调用了tryAcquiredShared,这两个try方法来自于AQS,分别用于在共享模式下线程释放锁和持有锁
1) 只有已经完成/取消的任务,才能即时获取结果。
2) 否则任务会等待执行完成或者被取消。
3) 取消节点是一定会生效的。