jkd-timer任务调度类小结

原理:任务TimerTask使用如scheduleAtFixedRate添加在Timer实例的后,会被添加Timer实例里一个叫TaskQueue,

TaskQueue这东西是优先队列,根据任务TimeTask的执行时间进行从小到大的排序,一个使用jdk数组为底层实现的二叉堆,二叉堆结构实现了这么个结果,TimerTask加进入来插入到数组的最后面,然后进行上浮操作fixUp()尽量把TimerTask往前排,如果TimerTask的执行时间是队列里最小的则会排到数组的第一位,如果是第二小则不一定会排到数据的第二位。

这个上浮操作,并不是一个一个比较然后上浮,而 index >> 1,类似二分法般的向前比较。

对应的还有一个下沉操作fixDown(),在Timer实例中的执行线程TimerTask执行完TimerTask后对TimerTask使用,把TimerTask从数组第一位不断按执行时间的从小到大,下沉到相应的位置,在这个过程中,还会吧当前执行时间最小的TimerTask上浮到第一位,

说到这里大致就明白这个二叉堆的作用了吧!保证队列中执行时间最小(即将要被执行)的TimerTask的权益,其它TimerTask保持大概的优先级正确即可。

TimerThread是Timer中的任务执行线程,Timer是个单线程的任务调度类,调度和执行都是同一条线程,就是说如果A任务执行超时了会影响B任务的执行,B任务就算执行时间到也要等A任务执行完,空出线程去执行下一个任务B,

这个线程类run()的干了什么?调用taskqueue的getMin()方法获取执行时间最小的任务(即数组第一个),取出来判断执行时间是否小于等于当前时间,小于等于则直接执行,大于则计算出还有多少毫秒可以执行,wait(n)等待N秒再执行TimerTask.run()。
然后再调用getMin()。。。嗯,这是个无限循环!

线程类的run()并不是调用fixDown()的还会根据是不是需要周期性执行的任务来执行,是则执行,不是则(这句表达有些问题)

void removeMin() {
    queue[1] = queue[size];
    queue[size--] = null;  // Drop extra reference to prevent memory leak
    fixDown(1);
}

timerthread在启动后,判断taskqueue是否有task可用,为空则wait().

while (queue.isEmpty() && newTasksMayBeScheduled)
    queue.wait();

另一边,task添加到Timer后,如果发现新添加的task是数组第一个

queue.add(task);
if (queue.getMin() == task)
    queue.notify();

则唤醒timerthread线程执行任务。

fixUp(), fixDown()源码实现

/**
 * Establishes the heap invariant (described above) assuming the heap
 * satisfies the invariant except possibly for the leaf-node indexed by k
 * (which may have a nextExecutionTime less than its parent's).
 *
 * This method functions by "promoting" queue[k] up the hierarchy
 * (by swapping it with its parent) repeatedly until queue[k]'s
 * nextExecutionTime is greater than or equal to that of its parent.
 */
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;
    }
}

/**
 * Establishes the heap invariant (described above) in the subtree
 * rooted at k, which is assumed to satisfy the heap invariant except
 * possibly for node k itself (which may have a nextExecutionTime greater
 * than its children's).
 *
 * This method functions by "demoting" queue[k] down the hierarchy
 * (by swapping it with its smaller child) repeatedly until queue[k]'s
 * nextExecutionTime is less than or equal to those of its children.
 */
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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值