补充部分---ScheduledThreadPoolExecutor类分析 线程池底层原理详解与源码分析( 四 )

4.DelayedWorkQueue类#take方法
public RunnableScheduledFuture<?> take() throws InterruptedException {final ReentrantLock lock = this.lock;lock.lockInterruptibly(); //加锁,响应中断try {// 死循环自旋for (;;) {RunnableScheduledFuture<?> first = queue[0]; //头节点// 队列为null,则等待在条件上if (first == null)available.await();//队列非空else {//判断延时时间是否满足条件long delay = first.getDelay(NANOSECONDS);if (delay <= 0L)return finishPoll(first);// 头节点时间没到,还不能取出头节点first = null; // 等待的时候,不要持有头节点if (leader != null)//已经存在leader线程,当前线程await阻塞available.await();else {//如果不存在leader线程,当前线程作为leader线程,并制定头结点的延迟时间作为阻塞时间Thread thisThread = Thread.currentThread();leader = thisThread;try {available.awaitNanos(delay);} finally {//leader线程阻塞结束if (leader == thisThread)leader = null;}}}}} finally {//leader线程没有阻塞,可以找到头结点,唤醒阻塞线程if (leader == null && queue[0] != null)available.signal();lock.unlock();}}5.DelayedWorkQueue类#grow方法
private void grow() {int oldCapacity = queue.length;int newCapacity = oldCapacity + (oldCapacity >> 1); //新容量为原来的1.5倍if (newCapacity < 0) // overflownewCapacity = Integer.MAX_VALUE;queue = Arrays.copyOf(queue, newCapacity); //从旧数组 复制到 新数组}6.DelayedWorkQueue类#remove方法
public boolean remove(Object x) {final ReentrantLock lock = this.lock;lock.lock(); //加锁try {int i = indexOf(x); //定位xif (i < 0) //节点元素不存在return false;setIndex(queue[i], -1);int s = --size;//末节点作为替代节点RunnableScheduledFuture<?> replacement = queue[s];queue[s] = null;//原本末节点处置空,便于GCif (s != i) {//下移,保证该节点的子孙节点保持特性siftDown(i, replacement);// queue[i] == replacement说明下移没有发生if (queue[i] == replacement)//上移,保证该节点的祖先节点保持特性siftUp(i, replacement);}return true;} finally {lock.unlock(); //加锁}}7.DelayedWorkQueue类#siftDown方法
//情况说明:一般发生在队列头结点任务被取出了;这时候头结点空闲 , 会把队列【可看做是数组的情况会更好理解】末尾的元素【看作是树的话,上层数据要比下层的要小】放入头结点,然后向下转移,达到保持优先队列的情况 。private void siftDown(int k, RunnableScheduledFuture<?> key) {int half = size >>> 1;while (k < half) {int child = (k << 1) + 1; //左子节点坐标RunnableScheduledFuture<?> c = queue[child]; //c表示左右子节点中的较小者,暂时是左int right = child + 1; //右子节点坐标//两者进行比较 , 且下标没有超出数据个数if (right < size && c.compareTo(queue[right]) > 0)c = queue[child = right]; //右节点更小的话要变更数据和记录下标//直至找到下层没有比自身小的元素时就停下if (key.compareTo(c) <= 0)break;queue[k] = c;setIndex(c, k);k = child;}queue[k] = key;setIndex(key, k);}8.DelayedWorkQueue类#finishPoll方法
// f是队列头节点(?。。。?private RunnableScheduledFuture<?> finishPoll(RunnableScheduledFuture<?> f) {int s = --size;RunnableScheduledFuture<?> x = queue[s];//取出队列尾节点的值(之后放到合适位置)queue[s] = null;//置空,便于GC// 尾节点从0开始向下遍历调整顺序if (s != 0)siftDown(0, x);setIndex(f, -1); //设置f的heapIndex属性return f;}1244574199069500L

推荐阅读