java.util.Timer 初步了解

来源:互联网 发布:淘宝奇葩差评 编辑:程序博客网 时间:2024/05/17 15:36

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

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

使用这几行代码之后,Timer本身会每隔5分钟调用一遍server.checkNewMail()方法,不需要自己启动线程。Timer本身也是多线程同步的,多个线程可以共用一个Timer,不需要外部的同步代码。

 在《The Java Tutorial》中有更完整的例子:

public class AnnoyingBeep {    Toolkit toolkit;    Timer timer;    public AnnoyingBeep() {    toolkit = Toolkit.getDefaultToolkit();        timer = new Timer();        timer.schedule(new RemindTask(),                   0,        //initial delay                   1*1000);  //subsequent rate    }    class RemindTask extends TimerTask {    int numWarningBeeps = 3;        public void run() {        if (numWarningBeeps > 0) {            toolkit.beep();        System.out.println("Beep!");        numWarningBeeps--;        } else {            toolkit.beep();                 System.out.println("Time's up!");            //timer.cancel(); //Not necessary because we call System.exit            System.exit(0);   //Stops the AWT thread (and everything else)        }        }    }    ...}


这段程序,每隔3秒响铃一声,并打印出一行消息。循环3次。程序输出如下:

<span style="font-size:14px;">Task scheduled.Beep!      Beep!      //one second after the first beepBeep!      //one second after the second beepTime's up! //one second after the third beep</span>


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

<span style="font-size:14px;">...public class ReminderBeep {    ...    public ReminderBeep(int seconds) {    toolkit = Toolkit.getDefaultToolkit();        timer = new Timer();        timer.schedule(new RemindTask(), seconds*1000);    }    class RemindTask extends TimerTask {        public void run() {            System.out.println("Time's up!");        toolkit.beep();        //timer.cancel(); //Not necessary because we call System.exit        System.exit(0);   //Stops the AWT thread (and everything else)        }    }    ...}</span>


注意

1. 有朋友来信问,希望自己的Task一直运行,而不是像上面的RemindTask那样仅循环3次。
这很简单,可能这位朋友把Task的作用理解有误,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. (liangyiqing)假如我在一个Timer类里面再定义一个Timer类,如果外层定义的时间是24小时循环一次,而内层定义的是1小时循环一次,意思就是当一个小时内层运行完一次之后,内层Timer释放资源,我想问,外层的Timer是不是也会释放,还是24小时之中一直都在占用?
我不太清楚你的占用资源是什么意思,如果你在Task中用到一些资源,这些资源应该在Task运行结束后即刻释放,尤其对竞态条件,更应该占用尽量少的时间。一般来说,一次Task的运行时间,将少于你设定的周期。否则,Task将在Timer中堆积起来。如果你要实现上面说的每24小时和每1小时两个周期的操作,可以使用一个Timer,schedule两个Task即可。

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

6. (austin1979 )请问,定时的时间能为变量,可以在程序中变化吗?定时器开启之后,其循环执行的时间是否可以进行更改。
一个Timer可以控制任意多个Task的不同周期设定的触发。也就是说,这个Timer类似于可以定多个时间的闹钟,比如我的手机就有3个闹钟 :)  。但是一旦一个Task 已经进行了schedule了,那么就不能再次进行设定。所以,也不可能再改变其周期、延迟等等设定了。可以看下面的代码:
          
  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;            }

7. (eqingtian)可不可以认为Timer就是一个线程的发射器?

Timer中仅有一个存储Task的Queue和一个调度所有Task的线程。不管你schedule几次,在Timer上加了几个Task,都只有一个后台的线程进行调度。


本文引用通过地址:http://blog.csdn.net/winneryong/article/details/357533


0 0
原创粉丝点击