掌握聚合最新动态了解行业最新趋势
API接口,开发服务,免费咨询服务

Java中三种停止Timer的核心方法(附完整代码示例和注意事项)

在Java开发中,java.util.Timer是常用的定时任务调度工具,它通过一个后台线程来执行被安排的任务。然而,如果Timer使用完毕后没有正确停止,其后台线程会一直存活,导致资源泄漏甚至JVM无法正常退出。本文将详细讲解三种停止Timer的核心方法,并附上完整代码示例和注意事项。

一、调用Timer.cancel()方法终止整个定时器

cancel()是Timer类提供的最直接、最常用的停止方法。调用后,Timer会丢弃所有已安排的任务,终止后台工作线程,且之后不能再向该Timer安排任何新任务。

import java.util.Timer;
import java.util.TimerTask;

public class TimerCancelDemo {
    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();

        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务执行中... " + System.currentTimeMillis());
            }
        }, 0, 1000); // 每秒执行一次

        // 主线程等待5秒后停止定时器
        Thread.sleep(5000);
        timer.cancel();
        System.out.println("定时器已终止");
    }
}

技术要点:cancel()方法不会中断正在执行中的任务,而是等待当前任务执行完毕后再终止线程。Timer被cancel后不可复用,如需重新调度任务必须创建新的Timer实例。此方法会终止该Timer下的所有任务,适合需要一次性彻底关闭定时器的场景。

二、调用TimerTask.cancel()方法取消单个任务

如果只需要停止某个特定任务而保留Timer继续运行其他任务,可以调用TimerTask实例的cancel()方法。该方法仅取消当前任务,不影响Timer中的其他任务。

import java.util.Timer;
import java.util.TimerTask;

public class TaskCancelDemo {
    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();

        TimerTask taskA = new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务A执行中...");
            }
        };

        TimerTask taskB = new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务B执行中...");
            }
        };

        timer.scheduleAtFixedRate(taskA, 0, 1000);
        timer.scheduleAtFixedRate(taskB, 0, 2000);

        // 3秒后仅取消任务A,任务B继续执行
        Thread.sleep(3000);
        taskA.cancel();
        System.out.println("任务A已取消,任务B继续运行");

        // 再等5秒后终止整个Timer
        Thread.sleep(5000);
        timer.cancel();
    }
}

技术要点:被取消的任务仍会保留在Timer的任务队列中,占用少量内存。如果频繁取消大量任务,应配合调用timer.purge()方法来清除队列中已取消的任务,释放内存。purge()方法返回被移除的任务数量。

三、通过标志位控制任务优雅停止

前两种方法都是"强制"停止,而通过标志位控制是一种更优雅、更灵活的方式。在任务的run()方法中检查一个volatile布尔标志,当标志变为false时,任务自行退出循环或调用this.cancel()。

import java.util.Timer;
import java.util.TimerTask;

public class FlagControlDemo {
    private static volatile boolean running = true;

    public static void main(String[] args) throws InterruptedException {
        Timer timer = new Timer();

        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                if (running) {
                    System.out.println("任务执行中... " + System.currentTimeMillis());
                } else {
                    System.out.println("收到停止信号,任务退出");
                    this.cancel();
                }
            }
        }, 0, 1000);

        // 5秒后将标志位设为false,触发任务自行停止
        Thread.sleep(5000);
        running = false;
        System.out.println("已发送停止信号");

        // 等待任务完成退出后再终止Timer
        Thread.sleep(2000);
        timer.cancel();
    }
}

技术要点:标志位必须声明为volatile,确保多线程环境下的可见性,即主线程修改标志后,Timer线程能立即感知到变化。此方式允许任务在停止前完成当前轮次的收尾工作(如关闭连接、刷写缓冲区),实现优雅停机。适合需要精细控制任务生命周期的场景。

四、注意事项

  1. Timer不可复用:Timer一旦被cancel(),其后台线程就会终止,不能再安排新任务。如需重新调度,必须创建新的Timer实例。

  2. 未捕获异常会杀死Timer线程:如果任务run()方法中抛出了未捕获的运行时异常,Timer的后台线程会静默终止,后续所有任务都不会再执行。务必在run()方法中用try-catch包裹所有业务逻辑。

  3. 非daemon Timer会阻止JVM退出:默认创建的Timer是非守护线程,如果程序结束时没有调用cancel(),JVM将无法正常退出。可以通过new Timer(true)创建守护线程模式的Timer,这样当程序中只剩下守护线程时JVM会自动退出。

  4. Timer是单线程模型:所有任务共享一个后台线程串行执行,如果某个任务执行时间过长,会阻塞其他任务的调度。对于任务较重或需要并发执行的场景,建议使用ScheduledExecutorService替代。

  5. 生产环境推荐ScheduledExecutorService:ScheduledExecutorService基于线程池实现,支持多线程并发执行、异常隔离(单个任务异常不影响其他任务)、更丰富的取消控制(通过ScheduledFuture.cancel()),是生产环境中的首选方案。

Java中三种停止Timer的核心方法(附完整代码示例和注意事项)

Java中停止Timer主要有三种核心方法:Timer.cancel()用于一次性终止整个定时器及其所有任务;TimerTask.cancel()用于精确取消单个任务而保留其他任务继续运行;标志位控制则提供了一种优雅停止的机制,允许任务在完成当前轮次后自行退出。在实际开发中,应根据业务需求选择合适的方法,同时注意异常捕获、线程类型设置和资源释放。对于复杂的生产环境,建议优先考虑使用ScheduledExecutorService替代Timer,以获得更好的线程管理能力和容错性。

声明:所有来源为“聚合数据”的内容信息,未经本网许可,不得转载!如对内容有异议或投诉,请与我们联系。邮箱:marketing@think-land.com

  • 手机三个月停机次数

    通过手机号码查询近3个月总停机次数标签信息,统计近3个月内停机的次数。

    通过手机号码查询近3个月总停机次数标签信息,统计近3个月内停机的次数。

  • 手机用户年龄评分

    通过手机号查询判断该号码实名用户年龄区间标签信息。

    通过手机号查询判断该号码实名用户年龄区间标签信息。

  • 手机近三个月话费评分

    通过三网运营商手机号码和指定月份,查询号码近3个月话费消费区间标签详情及评分。

    通过三网运营商手机号码和指定月份,查询号码近3个月话费消费区间标签详情及评分。

  • 营运车辆判定查询

    通过车架号或车牌号查询车辆是否为营运车辆

    通过车架号或车牌号查询车辆是否为营运车辆

  • VIN查车辆信息-精准版

    通过车架号查询车辆的如品牌名称、车系名称、车型、排量、排放标准、外形尺寸、轮胎规格、变速器类型、公告号、轴距等等详细信息

    通过车架号查询车辆的如品牌名称、车系名称、车型、排量、排放标准、外形尺寸、轮胎规格、变速器类型、公告号、轴距等等详细信息

0512-88869195
客服微信二维码

微信扫码,咨询客服

数 据 驱 动 未 来
Data Drives The Future