技术准备

当游戏开始时,空投物资和敌机纷纷入场,玩家飞机开始移动并发射导弹。当导弹击中敌机或者空投物资时,玩家飞机将获得分数或者增强火力。当敌机与玩家飞机发生碰撞时,游戏结束。移动到游戏面板外的敌机、空投物资和导弹将被删除。这些类似于动画的设计过程,将借助 Java 提供的 Timer 类予以实现。本节将重点介绍 Timer 类。

Timer类的概念

定时计划任务功能在 Java 中主要使用的就是 Timer 对象,该对象由于在内部使用多线程的方式进行处理,因此和多线程技术还是有非常大的关联。在 JDK 中,虽然 Timer 类主要负责计划任务的功能,也就是在指定的时间开始执行某一个任务,但封装任务的类却是 TimerTask 类。

下面将使用 Timer 类和 TimerTask 类编写一个程序:程序计划在 “2019-03-0100:00:00” 被运行,如果计划时间早于当前时间,则程序立即被运行;反之,则程序不被运行。具体代码如下:

  1. 创建一个 ExecuteNotes 类,用于记录程序被运行的日期和时间,该类通过继承 TimerTask 类和实现 run() 方法来自定义要执行的任务。具体代码如下:

    public class ExecuteNotes extends TimerTask {
        @Override
        public void run() {
            DateFormat dateFormat = RunOrNot.dateFormat.get();
            System.out.println("程序被运行的日期和时间是" + dateFormat.format(new Date()));
        }
    }
  2. 创建一个 RunOrNot 类,用于格式化程序被运行的日期和时间格式。具体代码如下:

    import java.text.DateFormat;import java.text.SimpleDateFormat;public class RunOrNot {
        public static final ThreadLocal<DateFormat> dateFormat = new ThreadLocal<DateFormat>() {
            @Override
            protected DateFormat initialValue() {
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }
        };
    }
  3. 创建可运行 Test 类,通过执行 Timer.schedule(TimerTask task,Date time) 在 “2019-03-01 00:00:00”(计划时间)运行程序。具体代码如下:

    import java.text.ParseException;public class Test {
        private static Timer timer = new Timer();
        public static void main(String[] args) throws ParseException {
            timer.schedule(new ExecuteNotes(), RunOrNot.dateFormat.get().parse("2019-03-01 00:00:00"));
        }
    }

Timer类的注意事项

正确并合理使用 Timer 类,才能达到预期的定时效果。使用 Timer 类的注意事项如下:

  • 创建一个 Timer 对象就是新启动了一个线程,但是这个新启动的线程,并不是守护线程,它一直在后台运行。将新启动的 Timer 线程设置为守护线程的代码如下:

    Timer timer = new Timer(true);
  • 提前:当计划时间早于当前时间,则程序立即被运行。

  • 延迟:TimerTask 是以队列的方式一个一个地按顺序运行程序的,因此执行的时间和预期的时间可能不一致。如果前面的程序消耗的时间较长,则后面的程序运行的时间会被延迟。延迟的程序具体开始的时间,就是依据前面程序的结束时间。

  • 周期性运行:Timer 对象通过调用 schedule(TimerTask task,Date firstTime,long period) 方法,可以实现从 firstTime 开始每隔 period 毫秒执行一次程序。

  • schedule(TimerTask task,long delay) 当前的时间为参考时间,在此时间基础上延迟制定的毫秒数后执行一次 TimerTask 程序。

  • schedule(TimerTask task,long delay,long period) 当前的时间为参考时间,在此基础上延迟制定的毫秒数,再以某一间隔时间无限次数地执行某一程序。