JDK5之前,工作单元和执行机制是混合的,JDK以后,将两者分开:
- 工作单元:Runable、Callable定义
 - 执行机制:Executor框架负责
Executor框架的两极调度模型
用户程序通过Executor框架将任务映射为固定线程
操作系统将用户线程映射为内核线程,CPU处理 
Excutor框架的结构概览
三大组成部分
- 任务:Runable、Callable
 - 任务调度执行:实现了ExecutorService的两个执行器,ThreadPoolExecutor和ScheduledThreadPoolExecutor
 任务执行结果:Future接口,主要是实现Future接口的FutureTask
整体类图
使用流程图
任务执行器
ThreadPoolExecutor
- FixedThreadPool
 - SingleThreadExecutor
 - SingleThreadExecutor
 
ScheduledThreadPoolExecutor
Callable
- Runable
任务结果
Future接口 
FixedThreadPool详解


- 提交一个任务,通过offer到SyncQueue中
 - 若有空闲的线程poll到了,就直接分配给这个线程
 - 若没有线程poll,则立即新建线程,进行poll操作
 

ScheduledThreadPoolExecutor详解
- 调用scheduleAtFixedRate()方法或者scheduleWith-FixedDelay()方法,会先延迟执行器中的DelayQueue中添加一个实现了RunnableScheduledFutur接口的ScheduledFutureTask。
 - 执行图
 

3.执行周期的实现
后面再说
ScheduledThreadPoolExecutor的实现
- 队列中元素:ScheduledFutureTask
 
ScheduledFutureTask
- long time:任务执行的具体时间
 - long sequenceNumber:被加入队列的序列号
 - long period:任务执行间隔周期
 
- DelayQueue.take()获取一个到期任务
 - 线程执行任务,并重设time=time+周期时间
 - 
DelayQueue中take的任务过程

 获取Lock锁
- 获取周期任务
- 若PriorityQueue空时,Condition等待
 - 若有元素,且队头元素时间大于当前时间,await到那个time
 - 可以获取到元素后,若队列不为空,唤醒所有线程
 
 - 释放锁
DelayQueue队列的add流程
 

- 获取Lock
 - 添加任务
- 向PriorityQueue添加任务
 - 若是头元素,唤醒所有等待的线程
 
 - 释放Lock
 
FutureTask详解
FutureTask除了实现Future接口,还实现了Runnable接口。因此FutureTask交给Executor后,调用线程直接执行 FutureTask.run()
FutureTask的3种状态
- 未启动:FutureTask.run()没有被执行之前
 - 已启动:调用了run但是没有运行完毕
 已完成
get方法
- 未启动或已启动:会阻塞线程
 - 已完成:抛出异常或返回结果
 
- cancel方法
- cancel(true)
- 未启动:任务将永远不被执行
 - 已启动:已中断方式试图停止
 
 - cancel(false)
- 未启动:同上
 - 已启动:正常运行完毕
 
 - 已完成的任务:cancel方法统一返回false
 
 - cancel(true)
 

FutureTask的使用
- 产生:ExecutorService.submit()
 - 可执行的操作
- get
 - cancel
 
 
FutureTask的实现
get的执行流程
- 调用AQS.acquireSharedInterruptibly(int arg)
- 成功,直接放回结果
 - 失败,进入等待队列,进入第2步
 
 - 其他线程release后,唤醒线程,当前线程获取后,离开等待队列,并唤醒后继线程
 - 最后返回结果或抛异常
 
所有调用get方法的线程会进入等待队列。 任务完成后,会先唤醒队头队列,之后依次传播唤醒
run方法流程
- 执行Callable.call
 - 原子更新状态,成功,则设置call()放回的结果,再AQS.release
 - 调用done()方法
 




