import java.util.Arrays; import java.util.TimerTask;
class TaskQueue {
/**
* 使用数组存为,数据是TimerTask类型
*/
private TimerTask[] queue = new TimerTask[128];
/**
* 任务队列的大小,queue[0]没有使用,queue[1]-queue[size]是排好序的
*/
private int size = 0;
int size() {
return size;
}
/**
*
*/
TimerTask getMin() {
return queue[1];
}
TimerTask get(int i) {
return queue[i];
}
/**
* 这里快速删除,并没有维护堆,可能是大神考虑到只有在TimerTask的purge中调用了改方法
* purge方法中如果删除了至少1个元素,就会调用heapify方法重新建堆
* 1 <= i <= size.
*/
void quickRemove(int i) {
assert i <= size;
queue[i] = queue[size];
queue[size--] = null; // 删除多余的引用,防止内存泄露
}
boolean isEmpty() {
return size==0;
}
/**
* 清除队列
*/
void clear() {
// 清除引用,避免内存泄露
for (int i=1; i<=size; i++)
queue[i] = null;
size = 0;
}
/**
* 添加一个新任务到队列作为叶子节点,然后从这个节点开始重新建堆
*/
void add(TimerTask task) {
// 保证数组的大小能够存放
if (size + 1 == queue.length)
queue = Arrays.copyOf(queue, 2*queue.length);
queue[++size] = task;
fixUp(size);
}
/**
* 自底向上重建堆,k>>1 整数k右移1位表示除以2 k>>1 ==>k/2
* 根据堆的性质可以知道一个节点k 的父节点可以表示为k/2
* 因此这个方法的从指定的节点k,依次检查和它的父节点的关系
* 如果父节点大于子节点就交换父节点与子节点(小顶堆,堆顶是最小的元素)
*/
private void fixUp(int k) {
while (k > 1) {
int j = k >> 1;
if (queue[j].nextExecutionTime <= queue[k].nextExecutionTime)
break;
TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
k = j;
}
}
/**
*自顶向下重建堆,k<<1 整数k向左移1位表示乘以2 k<<1 ==>k*2
*根据堆的性质知道,对于一个节点k,它的子节点分别为k*2 和k*2+1(如果存在)
*
*这个方法就是对于节点k如果存在子节点,则找到子节点中较小的一个和k进行比较交换
*/
private void fixDown(int k) {
int j;
while ((j = k << 1) <= size && j > 0) {
if (j < size &&
queue[j].nextExecutionTime > queue[j+1].nextExecutionTime)
j++; // j indexes smallest kid
if (queue[k].nextExecutionTime <= queue[j].nextExecutionTime)
break;
TimerTask tmp = queue[j]; queue[j] = queue[k]; queue[k] = tmp;
k = j;
}
}
/**
* 移除最小的(第一个),然后把最后一个元素移到堆顶,执行自顶向下重新建堆
*/
void removeMin() {
queue[1] = queue[size];
queue[size--] = null;
fixDown(1);
}
/**
* 最小元素改变,重新建堆
*/
void rescheduleMin(long newTime) {
queue[1].nextExecutionTime = newTime;
fixDown(1);
}
/**
* 重建堆,因为叶子节点满足条件了,所以从最后一个根节点开始
*/
void heapify() {
for (int i = size/2; i >= 1; i--)
fixDown(i);
}
}