你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

定时器Timer

2021/12/5 21:13:00

  在JDK中,Timer类的主要作用是设置计划任务,即在指定时间执行某个任务,它在内部使用多线程的方式进行处理,与Java多线程技术有着非常大的关联。
  以下为Timer类的简单使用示例

public class TimerTest {
    public static void main(String[] args) throws InterruptedException {
        Timer timer=new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务已执行完毕.......");
            }
        },new Date(System.currentTimeMillis()+10000));
        Thread.sleep(20000);
        timer.cancel();
    }
}

任务已执行完毕…

  该使用示例中使用了Timer类中的schedule( )方法,通过这个方法可以在指定时间执行某一个任务。该示例中schedule( )方法的参数为 schedule(TimerTask task, Date time),其中TimeTask类用于定义需要执行的任务,Date用于指定日期。
  schedule( )还有很多重载方法,例如:

  1. schedule(TimerTask task, Date Time, long delay),该方法可以让任务延时一段时间再执行。
  2. schedule(TimerTask task, Date firstTime, long period),该方法可以实现按指定间隔周期无线循环的执行某一任务。如以下代码所示:
public class TimerTest {
    public static void main(String[] args) throws InterruptedException {
        Timer timer=new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务执行......."+"执行时间为"+System.currentTimeMillis());
            }
        },new Date(System.currentTimeMillis()+1000),1000);
    }
}

任务执行…执行时间为1638709176118
任务执行…执行时间为1638709177206
任务执行…执行时间为1638709178232
任务执行…执行时间为1638709179248
任务执行…执行时间为1638709180254

  当创建Timer对象时,会启动一个非守护线程TimerThread,线程的作用是执行定时任务。该线程会一直运行,只有执行了Timer类中的cancel( )时,TimerThread线程才会被销毁。
  TimerTask是以队列的方式逐一按顺序执行的。每一个Timer实例中都有一个TaskQueue,用于存放TimerTask,当执行schedule方法时,TimerTask实例参数会被存入Timer类中的TaskQueue中。TimerThread线程会对TaskQueue中的TimerTask进行执行处理。
  Timer类中,TaskQueue会以锁的形式在操作TaskQueue的方法中出现,也就是各个线程对于TaskQueue的操作是互斥的,以此来保证线程安全。
  如果任务的计划执行时间早于当前时间,则任务会立即执行。如以下代码所示

public class TimerTest {
    public static void main(String[] args) throws InterruptedException {
        Timer timer=new Timer();
        long executeTime=System.currentTimeMillis()-1000;
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务执行......."+"执行时间为"+System.currentTimeMillis());
            }
        },new Date(executeTime));
        System.out.println("当前时间:"+System.currentTimeMillis());
        System.out.println("计划预定执行时间:"+executeTime);
    }
}

当前时间:1638709415468
任务执行…执行时间为1638709415468
计划预定执行时间:1638709414468

  对于需要循环执行的任务,Timer类中还提供一种方法 scheduleAtFixedRate( ),该方法与schedule方法的使用方式是一样的,那么两者之间有什么不同呢?
  scheduleAtFixedRate( )与schedule( )的区别在于,对于一个需要循环执行的任务,如果任务的实际开始时间与期望开始时间间隔之中,任务已需要循环执行多次但并未被执行,schedule会把这些未执行任务取消执行,而scheduleAtFixedRate会在任务实际开始之后,短时间内无间隔的补充执行这些未执行的任务。
  这就是scheduleAtFixedRate( )对于任务的执行的追赶特性。而schedule( )没有追赶特性。