ScheduledExecutorService 和Timer的区别

一、本质区别

  1. Timer
  • JDK 1.3 就有的单线程定时任务
  • 内部只有一个线程轮流执行所有任务
  • 基于绝对系统时间 System.currentTimeMillis()
  1. ScheduledExecutorService
  • JDK 1.5 JUC 并发包提供
  • 线程池,多个线程执行任务
  • 基于相对时间(纳秒),不依赖系统时间
  • 任务之间完全隔离

二、核心缺陷对比

  1. Timer 单线程,一个任务卡死,全部任务卡死

  2. Timer 任务抛出未捕获异常 → 整个 Timer 直接死亡

  3. Timer 依赖系统时间,改时间会导致任务执行异常

  4. ScheduledExecutorService 完全解决以上所有问题


三、代码案例对比

① Timer 代码示例

复制代码
import java.util.Timer;
import java.util.TimerTask;

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

        // 任务1:正常执行
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务1执行");
            }
        }, 0, 1000);

        // 任务2:10秒后抛异常
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("任务2抛出异常");
                // Timer 只要有一个任务抛异常,整个Timer线程死亡!所有任务停止!
                throw new RuntimeException("异常"); 
            }
        }, 3000);
    }
}

运行结果:

任务 1 执行几次 → 任务 3 秒后抛异常 → 整个程序所有定时任务全部停止!

② ScheduledExecutorService 代码示例

复制代码
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class ScheduledTest {
    public static void main(String[] args) {
        // 核心线程池2个
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);

        // 任务1:正常执行
        executor.scheduleAtFixedRate(() -> {
            System.out.println("任务1执行");
        }, 0, 1, TimeUnit.SECONDS);

        // 任务2:3秒后抛异常
        executor.schedule(() -> {
            System.out.println("任务2抛出异常");
            throw new RuntimeException("异常");
        }, 3, TimeUnit.SECONDS);
    }
}

运行结果:

任务 2 抛出异常 只影响自己! 任务 1 永远继续执行!

ScheduledExecutorService

Java 1.5 提供的 **** 线程池风格的定时任务工具 ,用来替代旧的 Timer 。父接口是 ExecutorService,所以本质就是一个支持延迟 / 周期性执行的线程池

常用方法

  1. schedule(Runnable, delay, unit)

    延迟一段时间执行一次

  2. scheduleAtFixedRate(Runnable, initialDelay, period, unit)

    固定速率执行 ,每隔 period 执行一次,不关心任务执行时长

  3. scheduleWithFixedDelay(Runnable, initialDelay, delay, unit)

    固定间隔执行任务执行结束后,再等 delay 才执行下一次

  4. schedule(Callable...)

    延迟执行并带返回值


最核心区别

FixedRate:固定频率

每隔 固定时间 启动一次,任务执行时间长会导致任务挤堆、并发执行

FixedDelay:固定延迟

任务结束 → 等延迟 → 再执行下一次 任务之间一定有固定空闲时间


优点(对比 Timer)

  1. Timer 是单线程,一个任务卡死全部卡死
  2. ScheduledExecutorService 是线程池,任务之间隔离
  3. 任务抛出异常不会杀死整个调度器
  4. 更精确、更稳定

底层是什么?

**内部用的是:DelayedWorkQueue(延迟阻塞队列)**按执行时间排序,线程不断拿 "到时间" 的任务执行。


面试一句话总结

ScheduledExecutorService 是 JUC 提供的基于线程池的定时任务组件,用来替代 Timer,支持延迟执行、固定频率、固定间隔三种定时策略;任务隔离、异常安全,底层基于延迟队列实现。

相关推荐
西西弗Sisyphus11 小时前
Qt 在无边框窗口上做一套换肤系统
开发语言·数据库·qt
西西弗Sisyphus11 小时前
Qt 启动 UsageStatistic 插件报错
开发语言·qt
NeoGressAI外贸数字化11 小时前
外贸独立站零询盘排查:从 Google Search Console 到 PageSpeed 的技术实操
开发语言·c++
无小道11 小时前
C/C++——异步编程小记
开发语言·c++·c++11
奇树谦11 小时前
Pimpl 模式(d-pointer)详解:如何解决 C++ 头文件过大、编译依赖和 ABI 兼容问题
开发语言·c++
user_admin_god11 小时前
一体化数据归集接口详细设计说明
java·大数据·spring boot·后端·spring
DevOpenClub11 小时前
Markdown、HTML 和 PPT 如何稳定交付:文档转换任务的幂等发布流程
开发语言·前端·c#·html·powerpoint
程序员夏洛11 小时前
谈谈你了解的最常见的几种设计模式,说说他们的应用场景
开发语言·python·模板方法模式
LlmCraft|大模型工程实践11 小时前
08. Docker Compose 一键编排:多容器应用的指挥家
java·spring cloud·eureka
小灰灰搞电子11 小时前
Rust+Slint 实现侧滑菜单栏源码分享
开发语言·rust·抽屉式菜单栏