Java Timer(定时调用、实现固定时间执行)(2)

  里面还有一个属性是:threadReaper, 它是Object类型,只是重写了finalize方法而已,是为了垃圾回收的时候,将相应的信息回收掉,做GC的回补,也就是当timer线程由于某种 原因死掉了,而未被cancel,里面的队列中的信息需要清空掉,不过我们通常是不会考虑这个方法的,所以知道java写这个方法是干什么的就行了。

  接下来看调度方法的实现:

  对于上面6个调度方法,我们不做一一列举,为什么等下你就知道了:
  来看下方法:

public void schedule(TimerTask task, long delay)

  的源码如下:

1 public void schedule(TimerTask task, long delay) {
2        if (delay < 0)
3            throw new IllegalArgumentException("Negative delay.");
4        sched(task, System.currentTimeMillis()+delay, 0);
5    }

  这里调用了另一个方法,将task传入,第一个参数传入System.currentTimeMillis()+delay可见为第一次需要执行的时间的 时间点了(如果传入Date,就是对象.getTime()即可,所以传入Date的几个方法就不用多说了),而第三个参数传入了0,这里可以猜下要么是 时间片,要么是次数啥的,不过等会就知道是什么了;另外关于方法:sched的内容我们不着急去看他,先看下重载的方法中是如何做的

  再看看方法:

public void schedule(TimerTask task, long delay,long period)

  源码为:

public void schedule(TimerTask task, long delay, long period) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, System.currentTimeMillis()+delay, -period);
    }

  看来也调用了方法sched来完成调度,和上面的方法唯一的调度时候的区别是增加了传入的period,而第一个传入的是0,所以确定这个参数为时间片, 而不是次数,注意这个里的period加了一个负数,也就是取反,也就是我们开始传入1000,在调用sched的时候会变成-1000,其实最终阅读完 源码后你会发现这个算是老外对于一种数字的理解,而并非有什么特殊的意义,所以阅读源码的时候也有这些困难所在。

  最后再看个方法是:

public void scheduleAtFixedRate(TimerTasktask,long delay,long period)

  源码为:

public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
      if (delay < 0)
          throw new IllegalArgumentException("Negative delay.");
      if (period <= 0)
          throw new IllegalArgumentException("Non-positive period.");
      sched(task, System.currentTimeMillis()+delay, period);
  }

  唯一的区别就是在period没有取反,其实你最终阅读完源码,上面的取反没有什么特殊的意义,老外不想增加一个参数来表示 scheduleAtFixedRate,而scheduleAtFixedRate和schedule的大部分逻辑代码一致,因此用了参数的范围来作为 区分方法,也就是当你传入的参数不是正数的时候,你调用schedule方法正好是得到scheduleAtFixedRate的功能,而调用 scheduleAtFixedRate方法的时候得到的正好是schedule方法的功能,呵呵,这些讨论没什么意义,讨论实质和重点:

  来看sched方法的实现体:

private void sched(TimerTask task, long time, long period) {
        if (time < 0)
            throw new IllegalArgumentException("Illegal execution time.");
 
        synchronized(queue) {
            if (!thread.newTasksMayBeScheduled)
                throw new IllegalStateException("Timer already cancelled.");
 
            synchronized(task.lock) {
                if (task.state != TimerTask.VIRGIN)
                    throw new IllegalStateException(
                        "Task already scheduled or cancelled");
                task.nextExecutionTime = time;
                task.period = period;
                task.state = TimerTask.SCHEDULED;
            }
 
            queue.add(task);
            if (queue.getMin() == task)
                queue.notify();
        }
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/b086d52ad23b6fcd2b747a22e47e91e3.html