Java中Timer和TimerTask使用

Java定时任务(一) Timer及TimerTask的案例解析及源码分析 Java定时任务(一) Timer及TimerTask的案例解析及源码分析 一、概述: 定时任务这个概念在Java的学习以及项目的开发中并不陌生,应用场景也是多种多样。比如我们会注意到12306网站在锁定车票的30分钟以内要进行车票费用的支付,否则订单会被取消;再比如我... 阅读详情

Java提供了轻量级的定时任务实现Timer,通过Timer我们可以实现定时执行任务,定时循环执行任务的功能,我们先看JavaDoc中关于Timer的说明

一种工具,线程用其安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行。
  与每个 Timer 对象相对应的是单个后台线程,用于顺序地执行所有计时器任务。计时器任务应该迅速完成。如果完成某个计时器任务的时间太长,那么它会“独占”计时器的任务执行线程。因此,这就可能延迟后续任务的执行,而这些任务就可能“堆在一起”,并且在上述不友好的任务最终完成时才能够被快速连续地执行。
  对 Timer 对象最后的引用完成后,并且 所有未处理的任务都已执行完成后,计时器的任务执行线程会正常终止(并且成为垃圾回收的对象)。但是这可能要很长时间后才发生。默认情况下,任务执行线程并不作为守护线程 来运行,所以它能够阻止应用程序终止。如果调用者想要快速终止计时器的任务执行线程,那么调用者应该调用计时器的 cancel 方法。
  如果意外终止了计时器的任务执行线程,例如调用了它的 stop 方法,那么所有以后对该计时器安排任务的尝试都将导致 IllegalStateException,就好像调用了计时器的 cancel 方法一样。
  此类是线程安全的:多个线程可以共享单个 Timer 对象而无需进行外部同步。
  此类不 提供实时保证:它使用 Object.wait(long) 方法来安排任务。
  实现注意事项:此类可扩展到大量同时安排的任务(存在数千个都没有问题)。在内部,它使用二进制堆来表示其任务队列,所以安排任务的开销是 O(log n),其中 n 是同时安排的任务数。
  实现注意事项:所有构造方法都启动计时器线程。

一、一个Timer的简单例子

/**
 * ----------------------------------------
 * 调度线程池
 * ----------------------------------------
 */
private final ThreadPoolExecutor executors = new ThreadPoolExecutor(100, 400, 60L, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
/**
 * 线程信息跟踪打印
 */
{
    Timer timer = new Timer(true);
    timer.schedule(new TimerTask() {
        @Override
        public void run() {
            LOG.info("==================统计执行线程池信息【开始】==================");
            LOG.info("核心线程数: " + executors.getCorePoolSize());
            LOG.info("最大线程数: " + executors.getMaximumPoolSize());
            LOG.info("活动线程数: " + executors.getPoolSize());
            LOG.info("排队任务数: " + executors.getQueue().size());
            LOG.info("==================统计执行线程池信息【结束】==================");
        }
    }, 1000*60, 1000*60);
}

运行起来后,就会在每60秒跟踪线程池的使用情况,便于在找到最合适的线程池的大小.

二、Timer&TimerTask源码分析
1. Timer部分(此处只截取关键部分代码)

//简单理解:存储需要执行任务的队列
private final TaskQueue queue = new TaskQueue();
//Timer所对应的的线程,所有的任务都是通过它来执行的
private final TimerThread thread = new TimerThread(queue);
public Timer(String name) {
        thread.setName(name);
        thread.start();
}
//只执行一次的任务
public void schedule(TimerTask task, long delay) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        sched(task, System.currentTimeMillis()+delay, 0);
}
//循环执行的
public void schedule(TimerTask task, long delay, long period) {
        if (delay < 0)
            throw new IllegalArgumentException("Negative delay.");
        if (period <= 0)
            throw new IllegalArgumentException("Non-positive period.");
        sched(task, System.currentTimeMillis()+delay, -period);
    }
    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;

        //Timer使用的是notify&wait机制进行线程同步
        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();//唤醒TimerThread开始跑任务
        }
    }

2.TimerThread部分

class TimerThread extends Thread {
    boolean newTasksMayBeScheduled = true;
    private TaskQueue queue;
    TimerThread(TaskQueue queue) {
        this.queue = queue;
    }
    public void run() {
        try {
            mainLoop();
        } finally {
            // Someone killed this Thread, behave as if Timer cancelled
            synchronized(queue) {
                newTasksMayBeScheduled = false;
                queue.clear();  // Eliminate obsolete references
            }
        }
    }

    /**
     * The main timer loop.  (See class comment.)
     */
    private void mainLoop() {
        while (true) {
            try {
                TimerTask task;
                boolean taskFired;
                synchronized(queue) {
                    // Wait for queue to become non-empty
                    while (queue.isEmpty() && newTasksMayBeScheduled)
                        queue.wait();
                    if (queue.isEmpty())
                        break; // Queue is empty and will forever remain; die

                    // Queue nonempty; look at first evt and do the right thing
                    long currentTime, executionTime;
                    task = queue.getMin();
                    synchronized(task.lock) {
                        if (task.state == TimerTask.CANCELLED) {
                            queue.removeMin();
                            continue;  // No action required, poll queue again
                        }
                        currentTime = System.currentTimeMillis();
                        executionTime = task.nextExecutionTime;
                        if (taskFired = (executionTime<=currentTime)) {
                            if (task.period == 0) { // Non-repeating, remove
                                queue.removeMin();
                                task.state = TimerTask.EXECUTED;
                            } else { // Repeating task, reschedule
                                queue.rescheduleMin(
                                  task.period<0 ? currentTime   - task.period
                                                : executionTime + task.period);
                            }
                        }
                    }
                    if (!taskFired) // Task hasn't yet fired; wait
                        queue.wait(executionTime - currentTime);
                }
                if (taskFired)  // Task fired; run it, holding no locks
                    task.run();
            } catch(InterruptedException e) {
            }
        }
    }
}

三、使用Timer的场景与缺陷(个人见解,如有问题还请指出)
适用场景:
1. 任务执行应该比较简单的,耗时的操作建议不要使用。
2. 任务不需要做集群间同步,就如我前面的例子仅仅是跟踪打印信息.
缺陷场景:
1. 由于Timer是单线程执行的,如果其中一个任务抛出了RuntimeException将导致整个Timer退出,如下例:

public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();
        final AtomicInteger counter = new AtomicInteger(0);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                int i = counter.incrementAndGet();
                System.out.println("当前线程:" + Thread.currentThread() + ",T1执行中,已将i自增到:" + i);
                if (i == 10) {
                    throw new RuntimeException("我只想抛出个异常玩玩!!");
                }
            }
        }, 1000, 1000);
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println("当前线程:" + Thread.currentThread() + "T2已执行执行,当前时间" + this.scheduledExecutionTime());
            }
        }, 1000, 500);

        Thread.sleep(1000 * 20);
    }

执行结果

当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:1
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602890826
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602891326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602891826
当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:2
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602892326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602892826
当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:3
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602893326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602893826
当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:4
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602894326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602894826
当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:5
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602895326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602895826
当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:6
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602896326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602896826
当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:7
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602897326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602897826
当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:8
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602898326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602898826
当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:9
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602899326
当前线程:Thread[Timer-0,5,main]T2已执行执行,当前时间1527602899826
Exception in thread “Timer-0” 当前线程:Thread[Timer-0,5,main],T1执行中,已将i自增到:10
java.lang.RuntimeException: 我只想抛出个异常玩玩!!
at TimerTest$1.run(TimerTest.java:20)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)

四、参考链接
1.JDK中的Timer和TimerTask详解
2.java之 Timer 类的使用以及深入理解

Java的定时器Timer和TimerTask使用全解析 在Java编程中,定时任务是一个常见的需求。无论是定期执行某些操作,还是在特定时间点执行任务,Java提供的Timer和TimerTask类就可以帮助我们轻松实现这些功能。今天将详细介绍如何使用这两个类,包括任务的执行和暂停。 阅读详情

相关推荐

Dzzoffice结合OnlyOffice 报错排查流程总结

首先访问 OnlyOffice 首页,如下图:出现上图仍旧不能说明你的 OnlyOffice 服务已经成功安装,我们需要启动 OnlyOffice 服务测试用例来检测,可以看到上图出现了两条命令,第一条命令是用来启动测试用例服务的,我们只需要在后台执行该命令即可,Windows环境是以管理员身份运行Windows PowerShell输入即可运行了。

小胡的博客 4597

java的timertask_Java 定时器(Timer,TimerTask)详解及实例代码

Java 定时器在JAVA中实现定时器功能要用的二个类是Timer,TimerTaskTimer类是用来执行任务的类,它接受一个TimerTask做参数Timer有两种执行任务的模式,最常用的是schedule,它可以以两种方式执行任务:1:在某个时间(Data),2:在某个固定的时间之后(int delay).这两种方式都可以指定任务执行的频率,本文有二个例子,一个是简单的一个是用了内部类1.简...

weixin_39542742的博客 3041

AR1020触摸控制器驱动开发:嵌入式I²C/SPI底层集成指南

电容式触摸控制器是现代嵌入式人机交互(HMI)系统的核心感知单元,其工作原理基于寄生电容变化检测与数字信号处理。Microchip AR1020 作为典型单芯片方案,内置硬件滤波、多点跟踪与手势识别引擎,通过I²C或SPI接口输出结构化事件数据,显著降低主控MCU负载。该类器件的技术价值在于平衡精度、功耗与实时性,广泛应用于工业HMI、医疗设备及车载终端等对可靠性要求严苛的场景。本文聚焦AR1020的寄存器映射、中断驱动模型、坐标解析机制及在STM32平台的HAL/LL级工程实现,涵盖硬件时序约束、固件配置

weixin_29323977的博客 600

Java的定时器Timer和定时任务TimerTask应用以及原理简析

记录:272 场景:Java JDK自带的定时器Timer和定时任务TimerTask应用以及原理简析。在JDK工具包:java.util中可以找到源码,即java.util.Timer和java.util.TimerTask。TimerTask实现Runnable接口的run方法。Timer的属性TimerThread thread继承Thread。因此,Timer天生就具备多线程属性。这个轻量级的定时器和定时任务,在多线程的场景中使用极其便利和灵活。...

zhangbeizhen18的博客 6317

汽车LED驱动芯片TPS92682-Q1 SPI接口配置与调试实战指南

SPI(串行外设接口)作为一种高速、全双工的同步串行通信总线,广泛应用于微控制器与外围设备之间的数据交换。其工作原理基于主从架构,通过时钟、数据线和片选信号实现设备间的精准时序控制。在汽车电子和工业控制领域,SPI因其简单高效、易于扩展的特性,成为配置复杂电源管理芯片、传感器和存储器的关键技术。通过SPI接口,工程师能够动态调整设备参数、实时读取状态信息,并实现复杂的故障诊断与保护策略,极大地提升了系统的灵活性与可靠性。本文以汽车级双通道LED恒流驱动器TPS92682-Q1为例,深入解析如何通过SPI接口

weixin_29185493的博客 288

Mac用户必看:Typora最新版永久激活+弹窗屏蔽保姆级教程(附崩溃解决方案)

本文为Mac用户提供了一份详尽的Typora最新版永久激活与弹窗屏蔽教程。通过修改关键JS文件,实现软件激活状态并彻底关闭成功提示弹窗。文章深入剖析了操作原理,并重点提供了解决由此引发的多文档崩溃问题的实用临时方案,同时客观讨论了该方法的局限性与潜在风险。

wine的专栏 2353

java定时器-Timer和TimerTask详解

1、例子入手 package pers.growing.test; import java.util.Timer; import java.util.TimerTask; public class Main { /** * 延迟100ms后,间隔1s打印出:hello world * * @param args * @throws Inte...

嘻哈的博客 5万+

MDT部署实战:除了Office,这些“装机必备”软件也能一键静默安装(含静默参数)

本文详细介绍了如何利用Microsoft Deployment Toolkit(MDT)实现企业级软件的静默安装,包括浏览器、开发工具和系统增强工具等“装机必备”软件的部署方案。通过命令行参数和MSI属性,IT运维团队可以高效构建标准化工作环境,提升部署效率并确保版本一致性。文章还提供了安装顺序控制、结果验证和常见问题排错等高级技巧。

weixin_26985923的博客 172

Java中Timer,TimerTask的使用

导读: 1 使用背景: 在nea的开发过程中,性能数据上报时候,需要在接受数据的时候,定时给RNC网元发送ACK消息(网管在收到数据帧后的T时间内必须回送确认给网元。该功能是确保在发送给网管的数据帧不足V个的情况下,网元仍然能够收到确认。) 所以需要在定时器未启动的情况下,接受到数据后启动定时器,然后在定时器到时的情况下发送ACK,停止定时器。 在java的util包中提供了定时器的类T

rainman的专栏 5814

数据结构——滑动窗口

入:下标为 i 的元素进入窗口,更新相关统计量。如果 i < k−1 则重复第一步更新:更新答案。一般是更新最大值 / 最小值出:下标为 i−k+1 的元素离开窗口,更新相关统计量✔1. 定长子串中元音的最大数目✔2. 找到一个数字的 K 美丽值✔4. 子数组的最大平均数 |方法一:前缀和方法二:滑动窗口7. 得到 K 个黑块的最少涂色次数8. 爱生气的书店老板9. 几乎唯一子数组的最大和10. 长度为 K 子数组中的最大和11. 可获得的最大点数12. 最少交换次数来组合所有的1 ||

qq_68915288的博客 762

YOLO26 正式发布源代码!极致速度优化方案, 面向工业级落地的目标检测模型!

YOLO26 作为 Ultralytics 公司于 2025 年 9 月发布的最新一代目标检测模型,在架构设计和技术实现上展现了显著的创新。本文深入分析了 YOLO26 的核心架构改进和技术原理,重点探讨了其在边界框回归、推理流程、损失函数设计和优化算法方面的突破性进展。

魔改工程师的博客 1243

使用Java中的Timer和TimerTask

      有的时候我们需要每隔一段时间去执行某个任务,在Java中提供了Timer and TimerTask来完成这个任务,本文提供一个应用程序的源代码告诉你如何使用这两个类。       Timer和TimerTask的方法很少,使用起来也非常方便。希望如果遇到问题参考一下API doc,里面写的很清楚。TimerTask是个抽象类,他扩展了Object并实现了Runnable接口,因此你必

mingjava的专栏 2万+

基于知识图谱的档案智慧问答系统:构建智能化档案管理与知识服务新范式

基于知识图谱的档案智慧问答系统是档案管理领域的一次重要创新,它通过将档案数据转化为结构化的知识图谱,并结合自然语言处理和智能问答技术,实现了档案信息的智能化管理与服务。该系统不仅能够提升档案管理的效率,还能为用户提供更全面、更便捷的知识服务,具有广泛的应用前景和深远的社会意义。未来,随着技术的不断进步和应用场景的不断扩展,基于知识图谱的档案智慧问答系统将在更多领域发挥其价值,为档案管理领域的智能化转型提供强有力的支持。

qq_62634009的博客 1577

java中timer和timertask_使用Java中的Timer和TimerTask

有的时候我们需要每隔一段时间去执行某个任务,在Java中提供了Timer and TimerTask来完成这个任务,本文提供一个应用程序的源代码告诉你如何使用这两个类。Timer和TimerTask的方法很少,使用起来也非常方便。希望如果遇到问题参考一下API doc,里面写的很清楚。TimerTask是个抽象类,他扩展了Object并实现了Runnable接口,因此你必须在自己的Task中实现p...

weixin_34312809的博客 225

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java中使用Timer和TimerTask实现多线程

摘要: Timer是一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask。 Timer是一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask。TimerTask是一个抽象类,实现了Runnable接口,所以具备了多线程的能力。 测试...

技术小学僧的博客 2409

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Java中Timer和TimerTask的使用

Java中Timer和TimerTask的使用

欢迎朋友,我是一名十多年开发经验的新手,希望多多指教。 314

Java中的Timer和TimerTask的使用

Timer是一个定时器类,通过该类可以为指定的定时任务进行配置。TimerTask类是一个定时任务类,该类实现了Runnable接口,而且是一个抽象类,如下所示:   public abstract class TimerTask implements Runnable   可以通过继承该类,来实现自己的定时任务。   Timer定时器实例有多种构造方法:   Timer()   创建一

曼诗雅先生 427

java timer和timertask,定时任务Java中Timer和TimerTask的使用

java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks。TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内。1.定制任务:TimerTaskTest.javapackage test;import java.util.Date;public class TimerTaskTest extends java.util.Tim...

weixin_36173034的博客 253

java 多线程 timer_Java中使用Timer和TimerTask实现多线程

Timer是一种线程设施,用于安排以后在后台线程中执行的任务。可安排任务执行一次,或者定期重复执行,可以看成一个定时器,可以调度TimerTask。TimerTask是一个抽象类,实现了Runnable接口,所以具备了多线程的能力。测试代码:1 importjava.util.TimerTask;23 public class OneTask extendsTimerTask{45 pri...

weixin_35749796的博客 643

定时任务:Java中Timer和TimerTask的使用

java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks。 <br />一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建。 <br /><br />一个完整的Timer: <br />Java代码 java.util.Timer timer = new java.util.Timer(true);    // true 说明这个timer以daemon方式运行(优先级低,    // 程

joshua_peng1985的专栏 1458
上一篇: 【Tomcat学习】getCanonicalFile与getAbsoluteFile区别
下一篇: 利用Spring扫描class文件
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值