- A+
之前介绍了线程池相关的对象,Runable Callable与Future,下面介绍FutureTask的作用,它的特性是怎样的呢?
FutureTask特点
先看FutureTask的类图:
从上图我们可以看到FutureTask实现了RunableFuture接口,同时RunableFuture又继承Future,Runable接口,也就是说FutureTask具备Runbale的run方法执行异步任务,也可以像Future一样能够控制任务的执行
内部成员变量
状态信息分为:
NEW:任务新建; COMPLETING:任务即将完成;NORMAL:正常执行结束; EXCEPTIONAL:任务出现异常
CANCELLED:任务取消,INTERRUPTING:任务中断中 ,INTERRUPTED:任务已中断。
状态转换的序列:
NEW -> COMPLETING -> NORMALNEW -> COMPLETING -> EXCEPTIONALNEW -> CANCELLEDNEW -> INTERRUPTING -> INTERRUPTED
其他变量:
核心方法
构造方法:FutureTask(Callable<V> callable)和FutureTask(Runnable runnable, V result),接收callable和Runable,和结果result。
run():
主要的流程:
如果当前状态不是NEW,或者调用CAS方法,判断RUNNER为null的话,都直接返回读取Callable 变量然后校验状态,执行call方法。如果执行call()的过程中发生异常,就调用设置异常信息,如果执行成功,则将执行set(result),设置结果如果业务逻辑异常,则调用setException方法将异常对象赋给outcome,并且更新state值最后会将runner设置为null,判断状态信息如果是INTERRUPTING,则表示正在被中断,交出线程执行权,让其他线程执行get()和get(long timeout, TimeUnit unit)
这个跟future的含义一致,get()阻塞等待,get(long timeout, TimeUnit unit),阻塞特定的时间。其中主要分析下awaitDone(false, 0L)这个方法的具体逻辑:
这是一个循环,如果当前线程被打断那么抛出异常,如果没有则取出状态信息s,如果s > COMPLETING,表示任务已经执行结束,或者出现异常结束,那么将等待节点中队列设置为null。s==COMPLETING 那么让出线程执行如果等待节点q为null,则闯将,并且将它插入到等待队列中,之后判断timed是否等待实现,如果是则计算具体时间执行LockSupport.parkNanos(this, nanos),等待具体的时间,否则LockSupport.parkNanos(this),进入一直阻塞状态。cancel(boolean mayInterruptIfRunning)1.如果子任务还没有执行,那么该任务执行停止,如果子任务已经执行,且mayInterruptIfRunning=true
,那么执行子任务的线程也会被中断
finishCompletion()
不管是什么样的任务,无论取消还是其他,最后都会调用finishCompletion()方法具体应用实例:
一个能够有控制的异步任务:
以上总结:
FutureTask作为一个可以控制的异步任务的存在,是对Runable实现一种继承和扩展,再这里我们熟悉它的一些用法和应用场景,对内部方法进行学习。多接口的继承是我们日后开发设计中需要掌握的
ps:如果您觉得对文章对您有帮助,欢迎收藏和关注,这将是对我最大肯定