avatar

一条在知识海洋的咸鱼

这个家伙很懒,啥也没有留下😋

  • 首页
  • Linux
  • OCJP
  • Java核心技术卷
  • J2EE相关标准
  • 深入理解Java虚拟机
  • NIO与SOcket编程技术指南
  • Java多线程编程核心技术
  • Redis开发与运维
  • Spring Cloud Alibaba 微服务原理与实践
  • DevOps
  • Docker
  • MySQL必知必会
  • AI自学路线
  • Spring Boot 编程思想(核心篇)
主页 定时器TImer
文章

定时器TImer

发表于 2021-11-12 更新于 2026-06- 10
作者 Administrator
19~24 分钟 阅读

Java的定时/计划功能功能
image.png
image.png

  • 定时器Timer相关类的使用
  • Timer相关API
    • void schedule(TimerTask task, Date time)
    • void cancel()销毁Timer线程
    • 执行时间花费过长,影响接下来执行的时间
    • void scheduleAtFixedRate(TimerTask task, Date firstTime,long period) 在指定日期之后重复周期执行该任务,如果起始时间在以前则立即执行
    • Timer和TimerTask的cancel()方法
    • schedule(TimerTask task,long delay,long period)定时间隔执行任务
    • void scheduleAtFixedRate(TimerTask task, long delay, long period) 具有追赶的特性

定时器Timer相关类的使用

  • Timer类
    设置计划任务,在指定时间开始执行某一任务
  • TimerTask抽象abstract类
    封装任务
  • TimerTask的子类
    执行具体执行任务

Timer相关API

image.png

void schedule(TimerTask task, Date time)

在指定时间执行一次任务,如果设置的时间已经超过则立即执行

//定时器
class AB{
    public static void main(String[] args) throws InterruptedException {
        long now = System.currentTimeMillis();
        System.out.println("当前时间为:"+now);
        long start = now + 1000;
        System.out.println("计划开始时间为:"+start);
        Timer timer = new Timer();
        Thread.sleep(100);
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("已经执行任务,时间为:" + System.currentTimeMillis());
            }
        };
        timer.schedule(timerTask,new Date(start));
        System.out.println("main线程走完时间为:"+System.currentTimeMillis());
    }
}

timer对象是执行定时任务
timerTask抽象类实现了Runable接口,其子类是执行具体的代码逻辑,重写run方法的
执行结果如下图
image.png
注意:此时main方法走完之后,定时线程因为不是守护线程还在继续走下去。但是定时任务走完之后线程并没有结束,还在运行

private void sched(TimerTask task, long time, long period) {
        if (time < 0)
            throw new IllegalArgumentException("Illegal execution time.");

        // Constrain value of period sufficiently to prevent numeric
        // overflow while still being effectively infinitely large.
        if (Math.abs(period) > (Long.MAX_VALUE >> 1))
            period >>= 1;

        synchronized(queue) {
            if (!thread.newTasksMayBeScheduled)
                throw new IllegalStateException("Timer already cancelled.");

            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;
            }

            queue.add(task);
            if (queue.getMin() == task)
                queue.notify();
        }
    }

执行schedule方法的时候将TimerTask加入queue的队列中
image.png
然后一直true死循环查找队列,如果队列为空则释放锁,但是死循环还是一直执行。所以线程不销毁

void cancel()销毁Timer线程

一定要注意虽然可以在run方法内部或者主线程使用,但是一定要确保调用此方法时是最后一条任务结束了,否则所有后续的定时任务都会失效
image.png

执行时间花费过长,影响接下来执行的时间

class AD{
    public static void main(String[] args) throws InterruptedException {
        long now = System.currentTimeMillis();
        System.out.println("当前时间为:"+now);
        long start = now + 1000;
        System.out.println("计划1开始时间为:"+start);
        long start2 = now + 2000;
        System.out.println("计划2开始时间为:" + start2);
        Timer timer = new Timer();
        Thread.sleep(100);
        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("已经执行1任务,时间为:" + System.currentTimeMillis());
                try {
                    Thread.sleep(20000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("执行1任务完毕,时间为:" + System.currentTimeMillis());
            }
        };
        TimerTask timerTask2 = new TimerTask() {
            @Override
            public void run() {
                System.out.println("已经执行2任务,时间为:" + System.currentTimeMillis());
            }
        };
        timer.schedule(timerTask,new Date(start));
        timer.schedule(timerTask2,new Date(start2));
//        Thread.sleep(2000);
//        timer.cancel();
        System.out.println("main线程走完时间为:"+System.currentTimeMillis());
    }
}

因为只有1个线程去执行,所以被阻塞了
image.png

void scheduleAtFixedRate(TimerTask task, Date firstTime,long period) 在指定日期之后重复周期执行该任务,如果起始时间在以前则立即执行

image.png

Timer和TimerTask的cancel()方法

TimerTask类的cancel方法是取消自身在队列queue的任务
Timer类的cancel方法是取消所有queue的任务
但不是会立即取消任务,有时候会没有抢到queue队列的锁,导致线程继续执行

class AH extends TimerTask {
    private int i;
    public AH(int i) {
        this.i = i;
    }
    @Override
    public void run() {
        System.out.println("第" + i + "次没有被cancel取消");
    }
}
class AG {
    public static void main(String[] args) {
        int i = 0;
        long now = System.currentTimeMillis();
        System.out.println("当前时间为:" + now);
        System.out.println("计划时间为:" + now);
        while (true) {
            i++;
            Timer timer = new Timer();
            AH ah = new AH(i);
            timer.schedule(ah, new Date(now));
            timer.cancel();
        }
    }
}

还是有没有抢到锁,继续执行的现象
image.png

schedule(TimerTask task,long delay,long period)定时间隔执行任务

不具有追赶的特性,从上一个任务结束的时间到下一个任务开始的时间
image.png
image.png

void scheduleAtFixedRate(TimerTask task, long delay, long period) 具有追赶的特性

具有追赶的特性,从上一个任务结束开始的时间到下一个任务开始的时间
例如Spring的@Schedule注解每个整点进行一次任务,其实用的底层是Excuter并发框架的定时
image.png

Java多线程编程核心技术
Java并发
许可协议: 
分享

相关文章

11月 13, 2021

线程其他

线程在不同的层次不同的说法与环境,就Java语言层次来说线程状态验证NEW、RUNNABLE、TERMINATED验证BLOCKED、WAITING、TIMED_WAITING线程状态就线程来说不同的层面有不同的说法。底层P(S),V(S)资源操作,编码层次对象锁操作,在Java层面对线程的状态定义

11月 12, 2021

单例模式与多线程

单利模式是经常使用到的设计模式,例如spring的默认bean为单例。同时众多框架体系使用的为多线程体系,所以在使用的时候单例和多线程结合起来可能会有一些没有注意到的事情,例如全局变量的控制等。单例模式的实现立即加载/饿汉模式单例模式的实现立即加载/饿汉模式

11月 12, 2021

定时器TImer

Java的定时/计划功能功能

下一篇

单例模式与多线程

上一篇

Lock对象的使用

最近更新

  • 55 异常兜底:工具失败、非法输出、空检索与超时
  • 54 Agent Memory:短期记忆、用户上下文与摘要
  • 53 Human-in-the-loop:让关键动作暂停、确认与恢复
  • 52 工单 Tool:字段校验、创建结果与失败补偿
  • 51 订单 Tool:Mock、鉴权、状态解析与脱敏

热门标签

java基础 微服务 maven Spring Tomcat DDD Linux Linux基础 SQL基础 数据结构算法

目录

©2026 一条在知识海洋的咸鱼. 保留部分权利。

使用 Halo 主题 Chirpy