传统线程机制之定时器的应用(TIMER,TIMERTASK)

定时器的应用(Timer,TimerTask)

定时器在项目当中也是会经常用到的,特别是做游戏的。比如俄罗斯方块不停的往下掉,贪吃蛇不停的往前走,人的这个移动,都是靠定时器每1秒钟,向前移动多少个像素,看起来就是一个动画效果。所以说,定时器用的也会很多。以下讲解在jdk1.5以前,使用定时器是怎么使用的。

Java用于描述定时器的类是Timer类。new Timer();就得到了一个定时器。定时器怎么启动呢?定时器是要调度的,通过schedule调度方法启动,比如第几点几分列车到站,第几点几分列车停下来,这些都是需要调度的。也就说,定时器去调度一个任务,去调度一个事件,这个事件具体的事情也是一个对象,用TimerTask类来描述。调度任务还需要指明时间,是在什么时间去干这个事。

TimerTask类:定时任务,这是一个抽象类,实现了Runnable接口,定义了一个抽象方法run。我们要执行的代码是放在一个类身上的方法里面,当我们new 一个TimerTask对象,是想执行我们的代码,也就是说,这个对象里面肯定要有一个方法,这个方法用来装我的代码。我要把一段代码交给你运行,我是怎么交的呢?我是直接把代码传给你,还是传一个对象给你?传一个对象,你拿到对象以后,调用我这个对象身上特定的某个方法去运行,我的代码也写在那个方法里面,是不是等于把我的代码教给你了。就这样的,把这个对象给他,这个对象有一个特定的方法,方法里面有代码,人家就会运行这个对象里面的特定方法代码。

public static void main(String[] args) {

        new Timer().schedule(new TimerTask() {

            @Override

            public void run() {

                System.out.println("bombing!");

            }

        }, 10000);

//没有下面的代码,上面的代码一样是10秒钟过后执行任务。

        while (true) {

            System.out.println(new Date().getSeconds());

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

public static void main(String[] args) {

        new Timer().schedule(new TimerTask() {

            @Override

            public void run() {

                System.out.println("bombing!");

            }

        }, 10000,3000);//第一次执行任务是10秒过后,之后每隔3秒都会执行一次该任务。

    }

思考题:可不可以这样,先是过2秒钟执行一次任务,再过4秒钟执行一次任务,一直以这样的事件频率来执行任务。也就是说,每次间隔的事件不一样,要交替的出现。(思路,在定时器里面再装一个定时器)注意,当任务对象已经被调度过后,不能再调度这个任务对象了。

两种方案:

1,  根据任务执行次数的奇偶来决定叠加的触发时间。

public class TraditionalTimerTest {

    private static int count = 0;

    public static void main(String[] args) {

        class MyTimerTask extends TimerTask {

            @Override

            public void run() {

                count = (count + 1) % 2;

                System.out.println("bombing!");

                new Timer().schedule(new MyTimerTask(), 2000 + 2000 * count);

            }

        }

        new Timer().schedule(new MyTimerTask(), 2000);

        while (true) {

            System.out.println(new Date().getSeconds());

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

}

2,  声明两种时间方法的定时器任务在run方法里面彼此调用对方的对象,实现交替执行;

public class TraditionalTimerTest2 {

    static class MyTimerTask2 extends TimerTask {

        @Override

        public void run() {

            System.out.println("bombing!");

            new Timer().schedule(new MyTimerTask(), 4000);

        }

    }

    static class MyTimerTask extends TimerTask {

        @Override

        public void run() {

            System.out.println("bombing!");

            new Timer().schedule(new MyTimerTask2(), 2000);

        }

    }

    public static void main(String[] args) {

       

        new Timer().schedule(new MyTimerTask2(), 2000);

        while (true) {

            System.out.println(new Date().getSeconds());

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                e.printStackTrace();

            }

        }

    }

}

思考题:每天凌晨3点执行任务,这个需求怎么做?

java.util.Timer.schedule(TimerTask, Date, long),第二个参数指定某个日期的晚上3点,第三个参数指定每个24小时的毫秒数。

public void scheduleAtFixedRate(TimerTask task,

                                Date firstTime,

                                long period)

安排指定的任务在指定的时间开始进行重复的固定速率执行。以近似固定的时间间隔(由指定的周期分隔)进行后续执行。

在固定速率执行中,相对于已安排的初始执行时间来安排每次执行。如果由于任何原因(如垃圾回收或其他后台活动)而延迟了某次执行,则将快速连续地出现两次或更多次执行,从而使后续执行能够赶上来。从长远来看,执行的频率将正好是指定周期的倒数(假定 Object.wait(long) 所依靠的系统时钟是准确的)。

固定速率执行适用于那些对绝对 时间敏感的重复执行活动,如每小时准点打钟报时,或者在每天的特定时间运行已安排的维护活动。它还适用于那些完成固定次数执行的总计时间很重要的重复活动,如倒计时的计时器,每秒钟滴答一次,共 10 秒钟。最后,固定速率执行适用于安排多次重复执行的计时器任务,这些任务相互之间必须保持同步。

参数:

task - 所要安排的任务。

firstTime - 首次执行任务的时间。

period - 执行各后续任务之间的时间间隔,单位是毫秒。

抛出:

IllegalArgumentException - 如果 time.getTime() 是负数。

IllegalStateException - 如果已经安排或取消了任务,已经取消了计时器,或者计时器线程已终止。

思考题:需求,定于工作日周一到周五的每天晚上的凌晨3点,收邮件。周六,周日休息,不收邮件。这个怎么实现?

这个就要使用你的数学功底了,根据日历来算了。这个就比较复杂了。可以借助开源的定时任务调度工具Quartz来实现。

Timer类:定时器

TimerTask类:定时任务,这是一个抽象类,实现了Runnable接口,定义了一个抽象方法run

猜你喜欢

转载自my.oschina.net/u/3512041/blog/1822006