Timer计时器

来源:互联网 发布:软件配置 编辑:程序博客网 时间:2024/04/28 20:48

Timer计时器

java.util这个包中可以找到Timer和TimerTask这两个类。Timer直接从Object 继承,它相当于一个计时器,能够用它来指定某个时间来执行一项任务,或者每隔一定时间间隔反复执行同一个任务。创建一个Timer后,就会生成一个线程在背后运行,来控制任务的执行。而TimerTask就是用来实现某项任务的类,它实现了Runnable接口,因此相当于一个线程。
如何实现自己的任务调度?

  1、继承TimerTask,注意TimerTask是实现Runnable接口的,因此只要重载run()方法即可。  2、创建Timer对象,调用schedule()方法。  相关注意点分析:    1、任务调度要优先考虑实时保证       由于Java的天性,并且在开发JDK的过程中要考虑到不同平台,而不同平台的线程调度机制是不同的,因此各种平台下JVM 的线程调度机制也是不一致的。从而Timer不能保证任务在所指定的时间内执行。另外由于TimerTask是实现Runnable接口的,在TimerTask被放进线程队列睡眠一段时间(wait)之后,当到了指定的该唤起该TimerTask时,由于执行的确切时机取决于JVM的调度策略和当前还有多少线程在等待CPU处理。因此就不能保证任务在所指定的时间内执行。通常在如下两种情况下导致任务延迟执行:      (1)、有大量线程在等待执行      (2)、GC机制的影响导致延迟

这也是为什么在Timer API中存在两组调度方法的原因。即:

      (1)、schedule()           用固定延迟调度。使用本方法时,在任务执行中的每一个延迟会传播到后续的任务的执行。      (2)、scheduleAsFixedRate()          用固定比率调度。使用本方法时,所有后续执行根据初始执行的时间进行调度, 从而希望减小延迟。具体使用哪一个方法取决于哪些参数对你的程序或系统更重要。 2、每个Timer对象要在后台启动一个线程。这种性质在一些托管的环境下不推荐使用,比如在应用服务器中。因为这些线程不在容器的控制范围之内了。具体Java API 中的Timer 类和TimerTask类的描述如下:                 java.util类Timer                 java.lang.Object                 java.util.Timer                 public class Timer                 extends Object 一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。 与每个Timer 对象相对应的是单个后台线程,用于顺序地执行所有计时器任务。计时器任务应该迅速完成。如果完成某个计时器任务的时间太长,

那么它会“独占”计时器的任务执行线程。因此,这就可能延迟后续任务的执行,而这些任务就可能“堆在一起”,并且在上述令人讨厌的任务最终完 成时才能够被快速连续地执行。

对Timer 对象最后的引用完成后,并且所有未处理的任务都已执行完成后,计时器的任务执行线程会正常终止(并且成为垃圾回收的对象)。但是

这可能要很长时间后才发生。默认情况下,任务执行线程并不作为守护线程来运行,所以它能够阻止应用程序终止。如果调用方想要快速终止计时器的任

务执行线程,那么调用方应该调用计时器的cancel 方法。

 如果意外终止了计时器的任务执行线程,例如调用了它的stop 方法,那么所有以后对该计时器安排任务的尝试都将导致IllegalStateException,就

好像调用了计时器的cancel 方法一样。

 此类是线程安全的:多个线程可以共享单个Timer 对象而无需进行外部同步。 此类不提供实时保证:它使用Object.wait(long) 方法来安排任务。 实现注意事项:此类可扩展到大量同时安排的任务(存在数千个都没有问题)。 在内部,它使用二进制堆来表示其任务队列,所以安排任务的开销是O(log n), 其中n 是同时安排的任务数。 实现注意事项:所有构造方法都启动计时器线程。
public static void main(String[] args) {        Timer timer=new Timer();        TimerTask   t1=new TimerTask(){            @Override            public void run() {                System.out.println(Thread.currentThread().getName());                System.out.println("t1 doing");            }        };        TimerTask t2=new TimerTask(){            @Override            public void run() {                System.out.println(Thread.currentThread().getName());                System.out.println("t2 doing");            }        };        Date date=new Date();        date.setMinutes(10);        timer.schedule(t1, new Date(), 12000);        System.out.println(Thread.currentThread().getName());        timer.schedule(t2,date, 12000);    }
有三个线程:Thread [DestroyJavaVM] (Running)          main          timer-0
0 0