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,支持延迟执行、固定频率、固定间隔三种定时策略;任务隔离、异常安全,底层基于延迟队列实现。

相关推荐
啊森要自信13 分钟前
【GUI自动化测试】控件、鼠标键盘操作与多场景自动化
c语言·开发语言·python·adb·ipython
花北城21 分钟前
【C#】ABP框架服务端开发
开发语言·c#·abp
电商API_1800790524726 分钟前
Python 实现闲鱼商品列表批量采集,接口异常重试机制搭建
大数据·开发语言·数据库·爬虫·python
DogDaoDao27 分钟前
深入理解 Qt:从原理到实战的全景指南
开发语言·qt·程序员
摇滚侠33 分钟前
SpringMVC 入门到实战 视图解析器 44-48
java·spring·maven·intellij-idea
放下华子我只抽RuiKe533 分钟前
FastAPI 全栈后端(四):认证与授权
开发语言·前端·javascript·python·深度学习·react.js·fastapi
記億揺晃着的那天44 分钟前
告别误操作!Spring Boot 多环境配置隔离与启动守卫实战
java·spring boot·后端·环境隔离
我是唐青枫1 小时前
Java Spring Data JPA 实战指南:Repository 查询、分页与实体映射
java·开发语言
张忠琳1 小时前
【Go 1.26.4】(Part 2) Go 1.26.4 超深度分析 — Runtime GMP 调度器 (proc.go + runtime2.go)
开发语言·golang
染翰1 小时前
Nacos 切换 Namespace 后配置不生效、占位符报错终极复盘
java·后端·spring·nacos