JUC FutureTask我的理解

clipboard.png

FutureTask是一个可取消的异步计算框架。其中内部用的是state来记录任务的执行状态。
clipboard.pngjava

如上所示FutrueTask内部封装了以上的Object。全部经过调用Futuretask执行的任务都会在齐内部包装成一个callable来执行。node

clipboard.png
clipboard.png

以上贴出的两个FutureTask的构造函数,要么直接构造一个实现了callable接口的对象,要么传入一个实现Runnable接口的对象,在其内部将Runnable转换为callable。多线程

FutureTask的执行:

接下来看看FutureTask的核心方法
clipboard.png框架

可经过将FutureTask放入一个线程,或者将其放入线程池中实现调用。其中set()和setException()会唤醒存在waiters中的node,告诉他们计算已经完成,或者计算中抛出了异常。
在set()、setException()和cancel()方法的末尾都会调用finishCompletion()方法来释放存在waiters中的线程,在该方法中还有一个done()方法,用来让子类实现,作一些异步任务完成以后的事情。
看看cancel()方法
clipboard.png异步

须要注意的是任务只有在state == NEW的时候才能被取消。函数


FutureTask结果的获取:

FutureTask可经过get()调用获得计算的结果,若是计算还没完成,该方法会阻塞,也可响应中断。产生阻塞的时候会将线程wrap成node加入到waiters中。下面看看get中调用的awaitDone(boolean timed, long nanos)方法
clipboard.pngthis

awaitDone代码中采起死循环的方式:
检查是否响应中断,如果,则移除该node,抛出中断异常。spa

if (Thread.interrupted()) {
    removeWaiter(q);
    throw new InterruptedException();
}

若此时已经结束,返回此时的状态值。线程

int s = state;
if (s > COMPLETING) {
    if (q != null)
    q.thread = null;
    return s;
}

若判断为如下状况则暂时让出cpu时间,稍后执行,由于COMPLETING是一个瞬时的状态,说明这个时候计算结果已经立刻要被set了,或者也多是抛出了异常。code

else if (s == COMPLETING) // cannot time out yet
          Thread.yield();

若判断为如下状况则新建一个node,该node包装了当前的线程。

else if (q == null)
         q = new WaitNode()

若判断为如下状况则将node加入到waiters中

else if (!queued)
    queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);

接下来最后的两个判断都是park这个线程,只是有时间的区分。

总结

利用FutureTask和ExecutorService,能够用多线程的方式提交计算任务,主线程继续执行其余任务,当主线程须要子线程的计算结果时,在异步获取子线程的执行结果。

相关文章
相关标签/搜索