具体实现代码如下:
private void finishCompletion() { for (WaitNode q; (q = waiters) != null;) { if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { for (;;) { Thread t = q.thread; if (t != null) { q.thread = null; LockSupport.unpark(t); } WaitNode next = q.next; if (next == null) break; q.next = null; q = next; } break; } } done(); callable = null; }代码实现很简单,看过get()方法后,我们知道所有调用get()方法的线程,在run()还没有返回结果前,都会保存到一个有WaitNode构成的statck数据结构中,而且每个线程都会被挂起。
这里是遍历waiters栈顶元素,然后依次查询起next节点进行唤醒,唤醒后的节点接着会往后调用report()方法。
FutureTask.report()实现原理具体代码如下:
private V report(int s) throws ExecutionException { Object x = outcome; if (s == NORMAL) return (V)x; if (s >= CANCELLED) throw new CancellationException(); throw new ExecutionException((Throwable)x); }这个方法很简单,因为执行到了这里,说明当前state状态肯定大于COMPLETING,判断如果是正常返回,那么返回outcome数据。
如果state是取消状态,抛出CancellationException异常。
如果状态都不满足,则说明执行中出现了差错,直接抛出ExecutionException
FutureTask.cancel()实现原理 public boolean cancel(boolean mayInterruptIfRunning) { if (!(state == NEW && UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED))) return false; try { if (mayInterruptIfRunning) { try { Thread t = runner; if (t != null) t.interrupt(); } finally { UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); } } } finally { finishCompletion(); } return true; }cancel()方法的逻辑很简单,就是修改state状态为CANCELLED,然后调用finishCompletion()来唤醒等待的线程。
这里如果mayInterruptIfRunning,就会先中断当前线程,然后再去唤醒等待的线程。
总结FutureTask的实现原理其实很简单,每个方法基本上都画了一个简单的流程图来方便立即。
后面还打算分享一个BlockingQueue相关的源码解读,这样线程池也可以算是完结了。
在这之前可能会先分享一个SpringCloud常见配置代码分析、最佳实践等手册,方便工作中使用,也是对之前看过的源码一种总结。敬请期待!
欢迎关注: