这是定时任务的线程池,用户通过
schedule,scheduleAtFixedRate,scheduleWithFixedDelay
把定时任务加入到堆队列中,工作线程取出队列头元素,当任务执行完成后,重新设置任务的执行时间,放回到队列中。
使用过程中,有几点需要注意:
1. scheduleAtFixedRate 和 scheduleWithFixedDelay 的任务执行时间不同
scheduleAtFixedRate 提交的任务,执行时间是 t, t+p, t+2p
scheduleWithFixedDelay 提交的任务,执行时间是前一次任务执行完成时间加上 period
2. 如果提交的定时任务执行过程中出现异常,并且没有捕获,导致异常被抛出,后续的定时任务不会再执行
3. 工作线程有 leader-follower 之分
假定工作线程没有 leader-follower 区分,则 2 个线程尝试获取堆顶的任务,发现该任务并没有到期,则挂起线程 t 时间,t 时间后,2 个线程被唤醒,再次尝试获取堆顶的任务,只有一个线程能获取到任务,另一个线程获取失败由被挂起,这样的挂起-唤醒-挂起,做了很多无用功。
采用 leader-follower 模式后,则 2 个线程尝试获取堆顶的任务,发现该任务并没有到期,则抢占 leader,leader 挂起线程 t 时间,其他线程一直挂起,leader 线程取到堆顶元素后,重置 leader 为 null ,并唤醒其他挂起的线程。