Java的FutureTask实现原理
2018-05-11 本文已影响86人
缄默的石头
Java的FutureTask实现原理
-
Executor.submit(Callable call)
submit步骤:- 将callable包装成一个FutureTask,这个类既是一个Future,又是一个Runnable,实现了RunnableFuture接口(适配器模式)
- 线程池提交任务
提交任务:将任务包装成一个worker,这个worker既持有任务,又持有线程(线程池中实际持有的是worker)。worker添加到线程池后,启动线程。执行逻辑如下:- 执行worker持有的任务
- 任务执行完了以后设置FutureTask的outCome
- 唤醒在FutureTask上面等待的线程WaitNode结构(java.util.concurrent.FutureTask#finishCompletion)
- 从线程池中的阻塞队列中获取新的任务(在这里控制线程的存活时间),如果获取到新的元素,执行步骤1
- 从线程池中移除worker,任务结束
- 返回futureTask
-
Future.get()
- 如果任务已经计算出来结果,直接返回结果
- 否则构建将当前线程包装成一个WaitNode(链表),CAS把生成的waitNode插入到FutureTask的header,然后挂起当前线程。(java.util.concurrent.FutureTask#awaitDone)
线程池的执行流程
- 如果线程池中thread的size小于coreSize,新建线程执行任务
- 如果线程池中的thread数量大于coresize,将任务添加到任务队列中(尽可能高效的复用线程)
- 如果任务不能添加到任务队列并且thread的size小于maxSize,新建线程执行任务
- 执行拒绝策略