醋醋百科网

Good Luck To You!

Java并发工具:ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor 是 Java 中用于执行定时任务和周期性任务的线程池实现类,它是 ThreadPoolExecutor 的子类,并实现了 ScheduledExecutorService 接口。它非常适合用来替代传统的 Timer 类,尤其是在高并发、需要调度多个任务的场景中。

一、核心功能

ScheduledThreadPoolExecutor 支持以下几种常见的任务调度方式:

1. 延迟执行一次任务

schedule(Runnable command, long delay, TimeUnit unit)

延迟一段时间后执行一次任务。

示例:

ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
executor.schedule(() -> System.out.println("Task executed after 5 seconds"), 5, TimeUnit.SECONDS);

2. 延迟执行并返回结果

<T> ScheduledFuture<T> schedule(Callable<T> callable, long delay, TimeUnit unit)

适用于有返回值的任务。

示例:

ScheduledFuture<Integer> future = executor.schedule(() -> {
return 42;
}, 3, TimeUnit.SECONDS);
System.out.println(future.get()); // 输出:42

3. 固定频率执行(fixed-rate)

scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
从初始延迟开始,每隔固定时间执行一次任务。
如果任务执行时间超过间隔时间,下一次任务会在当前任务结束后立即执行,不会累积间隔。

示例:

executor.scheduleAtFixedRate(() -> {
System.out.println("Running every 2 seconds");
}, 0, 2, TimeUnit.SECONDS);

4. 固定延迟执行(fixed-delay)

scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
  • 每次任务执行完成后,再等待固定时间才开始下一次任务。
  • 不受任务执行时间的影响,保证两次任务之间至少间隔为 delay。

示例:

executor.scheduleWithFixedDelay(() -> {
try {
Thread.sleep(1000); // 模拟耗时操作
} catch (InterruptedException e) {}
System.out.println("Task completed, waiting next run...");
}, 0, 2, TimeUnit.SECONDS);

二、内部原理

1. 使用了 DelayedWorkQueue

这是一个基于堆实现的延迟队列(Delayed接口),每个任务都有一个触发时间。队列会根据任务的执行时间排序,优先级高的任务先执行。

2. 核心线程数 >= 1

即使没有任务提交,核心线程也会保持活跃状态,避免频繁创建销毁线程。

3. 支持多线程调度

不像 Timer 只有一个线程,ScheduledThreadPoolExecutor 可以使用多个线程来处理任务,提高并发能力。

三、常见使用场景

场景

示例

定时任务

每天凌晨清理日志

心跳检测

客户端与服务端维持连接的心跳包

缓存刷新

定期更新本地缓存数据

轮询检查

定期轮询数据库或文件变化

四、注意事项

正确关闭线程池

不要忘记在程序结束时关闭线程池,否则可能导致程序无法退出。

executor.shutdown(); // 等待所有已提交任务完成
// 或者
executor.shutdownNow(); // 尝试停止所有正在执行的任务

避免任务堆积

如果任务执行时间过长,而你又用了 scheduleAtFixedRate,可能会导致任务堆积。建议根据业务选择合适的调度策略。

异常处理

任务中抛出异常会导致后续任务不再执行,因此务必加上 try-catch。

executor.scheduleAtFixedRate(() -> {
try {
// your code
} catch (Exception e) {
e.printStackTrace();
}
}, 0, 1, TimeUnit.SECONDS);

五、对比 Timer 和 ScheduledThreadPoolExecutor

特性

Timer

ScheduledThreadPoolExecutor

单线程/多线程

单线程

多线程

异常影响

一个任务异常 → 整个Timer失效

一个任务异常不影响其他任务

并发能力

调度灵活性

有限

更灵活(支持 fixed-rate / fixed-delay)

推荐程度

不推荐

推荐使用

六、完整示例代码

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class ScheduledThreadPoolExample {
    public static void main(String[] args) {
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);

        // 延迟任务
        executor.schedule(() -> System.out.println("After 3s"), 3, TimeUnit.SECONDS);

        // 固定频率执行
        ScheduledFuture<?> rateTask = executor.scheduleAtFixedRate(() -> {
            System.out.println("Fixed Rate Task");
        }, 0, 1, TimeUnit.SECONDS);

        // 固定延迟执行
        ScheduledFuture<?> delayTask = executor.scheduleWithFixedDelay(() -> {
            System.out.println("Fixed Delay Task");
        }, 0, 2, TimeUnit.SECONDS);

        // 模拟运行一段时间后关闭
        executor.schedule(() -> {
            rateTask.cancel(false);
            delayTask.cancel(false);
            executor.shutdown();
        }, 10, TimeUnit.SECONDS);
    }
}


总结

功能

方法

延迟执行

schedule(Runnable, delay, unit)

延迟执行并返回结果

schedule(Callable, delay, unit)

固定频率

scheduleAtFixedRate(...)

固定延迟

scheduleWithFixedDelay(...)

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言