使用java.util.Timer 分享修改删除

在应用开发中,经常需要一些周期性的操作,比如每5分钟检查一下新邮件等。对于这样的操作最方便、高效的实现方式就是使用java.util.Timer工具类。比如下面的代码每5分钟检查一遍是否有新邮件:

  1.         private  java.util.Timer  timer;
  2.         timer = new  Timer (true );
  3.         timer.schedule(new  java.util.TimerTask () {
  4.             public  void  run() {
  5.                     //server.checkNewMail(); 检查新邮件
  6.             }
  7.         }, 0, 5*60*1000);


使用这几行代码之后,Timer本身会每隔5分钟调用一遍server.checkNewMail()方法,不需要自己启动线程。Timer本身也是多线程同步的,多个线程可以共用一个Timer,不需要外部的同步代码。
    在《The Java Tutorial》中有更完整的例子:

  1. public  class  AnnoyingBeep {
  2.     Toolkit  toolkit;
  3.     Timer  timer;
  4.     public  AnnoyingBeep() {
  5.     toolkit = Toolkit .getDefaultToolkit();
  6.         timer = new  Timer ();
  7.         timer.schedule(new  RemindTask(),
  8.                    0,        //initial delay
  9.                    1*1000);  //subsequent rate
  10.     }
  11.     class  RemindTask extends  TimerTask  {
  12.     int  numWarningBeeps = 3;
  13.         public  void  run() {
  14.         if  (numWarningBeeps > 0) {
  15.             toolkit.beep();
  16.         System .out.println("Beep!" );
  17.         numWarningBeeps--;
  18.         } else  {
  19.             toolkit.beep(); 
  20.                 System .out.println("Time's up!" );
  21.             //timer.cancel(); //Not necessary because we call System.exit
  22.             System .exit(0);   //Stops the AWT thread (and everything else)
  23.         }
  24.         }
  25.     }
  26.     ...
  27. }

这段程序,每隔3秒响铃一声,并打印出一行消息。循环3次。程序输出如下:
Task scheduled.
Beep!      
Beep!      //one second after the first beep
Beep!      //one second after the second beep
Time's up! //one second after the third beep

Timer类也可以方便地用来作为延迟执行,比如下面的代码延迟指定的时间(以秒为单位)执行某操作。类似电视的延迟关机功能。

  1. ...
  2. public  class  ReminderBeep {
  3.     ...
  4.     public  ReminderBeep(int  seconds) {
  5.     toolkit = Toolkit .getDefaultToolkit();
  6.         timer = new  Timer ();
  7.         timer.schedule(new  RemindTask(), seconds*1000);
  8.     }
  9.     class  RemindTask extends  TimerTask  {
  10.         public  void  run() {
  11.             System .out.println("Time's up!" );
  12.         toolkit.beep();
  13.         //timer.cancel(); //Not necessary because we call System.exit
  14.         System .exit(0);   //Stops the AWT thread (and everything else)
  15.         }
  16.     }
  17.     ...
  18. }


===========================================================

一些注意的问题:

1. 如果希望自己的Task一直运行,而不是像上面的RemindTask那样仅循环3次。
这 很简单,Task仅代表了一次的动作。而不是让Task完成循环。上面的RemindTask中之所以有一个计数,是因为要运行3次停止,如果需要一直保 持运行。把上面有关的计数的代码全部去除即可。其实Timer中并没有提供运行指定次数后即停止的机制,所以,上面的计数满足了这个功能需要。

2. 能否设置Timer的优先级?
Timer 中是利用一个线程来进行计时及周期触发动作的。现在的Timer实现中并没有提供设置优先级的方法,在你调用new Timer()时线程已经启动,所 以,除非Timer的以后版本中在构造方法中增加优先级参数,否则,我们是不能控制其优先级的。现在的Timer默认是在 Thread.NORM_PRIORITY优先级下运行的。但是Timer提供了一个Timer(boolean isDaemon)的构造方法,可以将 Timer设置为daemon线程。这样,在你的程序中其它线程都运行完毕后,程序就可以退出了。

3. Timer是不是实现了精确地定时?
否。Timer中也是采用Object.wait(long time)来实现定时的,由于Object.wait()不保证精确计时,所以Timer也不是一个精确的时钟。如果是实时系统,不能依赖Timer。

4. 假如在一个Timer类里面再定义一个Timer类,外层定义的时间是24小时循环一次,而内层定义的是1小时循环一次,意思就是当一个小时内层运行完一次之后,内层Timer释放资源,那么外层的Timer是不是也会释放,还是24小时之中一直都在占用?
不 太清楚此占用资源是什么意思,如果在Task中用到一些资源,这些资源应该在Task运行结束后即刻释放,尤其对竞态条件,更应该占用尽量少的时间。一般 来说,一次Task的运行时间,将少于你设定的周期。否则,Task将在Timer中堆积起来。如果要实现上面说的每24小时和每1小时两个周期的操作, 可以使用一个Timer,schedule两个Task即可。

5. Timer是否可以在多线程环境下使用?
可以。Timer中用于存储Task的容器是同步了的,保证了多线程环境先的安全使用。

6. 定时的时间能为变量,可以在程序中变化吗?就是说定时的时间可以又界面来控制。
一 个Timer可以控制任意多个Task的不同周期设定的触发。也就是说,这个Timer类似于可以定多个时间的闹钟,比如我的手机就有3个闹 钟 :)  。但是一旦一个Task 已经进行了schedule了,那么就不能再次进行设定。所以,也不可能再改变其周期、延迟等等设定了。可以看下面 的代码:

  1.             synchronized (task.lock) {
  2.                 if  (task.state != TimerTask .VIRGIN)
  3.                     throw  new  IllegalStateException (
  4.                         "Task already scheduled or cancelled" );
  5.                 task.nextExecutionTime = time;
  6.                 task.period = period;
  7.                 task.state = TimerTask .SCHEDULED;
  8.             }


7. 可不可以认为Timer就是一个线程的发射器?
Timer中仅有一个存储Task的Queue和一个调度所有Task的线程。不管你schedule几次,在Timer上加了几个Task,都只有一个后台的线程进行调度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值