
🔍 开发者资源导航 🔍 |
---|
🏷️ 博客主页 : 个人主页 |
📚 专栏订阅 : JavaEE全栈专栏 |
Timer
Timer 是 Java 提供的一个简单的任务调度工具(位于 java.util 包),用于在指定的时间执行任务(一次性或周期性执行)。
Timer 的主要作用
-
定时任务
:在指定的延迟后执行一次任务。 -
周期性任务
:按照固定的时间间隔重复执行任务
Timer 的核心方法
方法 | 说明 |
---|---|
schedule(TimerTask task, long delay) |
延迟 delay 毫秒后执行一次任务 |
schedule(TimerTask task, Date time) |
在指定的 Date 时间执行一次任务 |
schedule(TimerTask task, long delay, long period) |
延迟 delay 毫秒后开始,每隔 period 毫秒重复执行任务 |
scheduleAtFixedRate(TimerTask task, long delay, long period) |
延迟 delay 毫秒后开始,以固定速率(period 毫秒)重复执行任务 |
cancel() |
终止 Timer ,取消所有已安排的任务 |
使用实例
java
import java.util.Timer;
import java.util.TimerTask;
public class demo18 {
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 1000");
}
}, 1000); // 1秒后执行
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 2000");
}
}, 2000); // 2秒后执行
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 3000");
}
}, 3000); // 3秒后执行
}
}
java
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 1000");
}
}, 1000, 1000); // 每隔1s执行一次
缺点
-
单线程执行
:所有任务都在同一个线程中执行,如果一个任务执行时间过长,会影响其他任务的调度。 -
异常影响全局
:如果某个任务抛出未捕获的异常,整个 Timer 会终止,后续任务不会执行。 -
时间精度依赖系统时钟
:如果系统时间被调整(如手动修改时间),可能导致任务执行不准确。
ScheduledExecutorService
由于 Timer 的局限性,Java 5 引入了
ScheduledExecutorService
(属于java.util.concurrent 包),它使用线程池,更稳定、更灵活,推荐在新代码中使用。
创建方式
使用线程池的工厂类
java
创建单线程的ScheduledExecutorService,任务量少,需顺序执行
Executors.newSingleThreadScheduledExecutor()
创建n个线程的ScheduledExecutorService,高并发任务,需并行执行
Executors.newScheduledThreadPool(n)
创建n个线程的ScheduledExecutorService,并设置拒绝方法
Executors。ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)
直接创建
java
可以设置工厂方法,拒绝方法,以及核心数目
ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler)
推荐使用
-
如果只是普通定时任务 → 推荐 Executors.newScheduledThreadPool()(更简洁)。
-
如果需要定制线程池(如调整拒绝策略、线程工厂) → 使用 new ScheduledThreadPoolExecutor()。
使用方法
使用 ScheduledExecutorService 进行任务调度时,可以通过不同的方法设置任务的执行方式,主要包括
延迟执行、固定速率执行 和 固定延迟执行。
延迟执行(单次任务)
参数:
java
schedule(Runnable command, long delay, TimeUnit unit)
特点:
- 任务 只会执行一次
- 在指定的 delay 时间后执行。
使用场景
:只需要在某个时间点执行一次的任务(如延迟初始化、超时任务)。
示例:
java
executor.schedule(() -> {
System.out.println("Task runs after 3 seconds");
}, 3, TimeUnit.SECONDS);
固定速率执行(Fixed Rate)
参数:
java
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
特点:
-
按照固定频率执行,不受任务执行时间影响。
-
如果任务执行时间超过 period,下一次任务会 立即开始(可能并发执行)。
使用场景
:适用于 严格周期性的任务(如定时数据同步)。
示例:
java
// 初始延迟 1 秒,之后每 2 秒执行一次(不管任务执行多久)
executor.scheduleAtFixedRate(() -> {
System.out.println("Fixed Rate Task - " + System.currentTimeMillis());
}, 1, 2, TimeUnit.SECONDS);
固定延迟执行(Fixed Delay)
参数:
java
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
特点:
- 任务执行完成后,再等待 delay 时间后执行下一次。
使用场景
:适用于 需要保证任务执行间隔 的场景(如心跳检测)
示例:
java
// 初始延迟 1 秒,每次任务结束后等 2 秒再执行下一次
executor.scheduleWithFixedDelay(() -> {
System.out.println("Fixed Delay Task - " + System.currentTimeMillis());
}, 1, 2, TimeUnit.SECONDS);
手写一个Timer
参数
java
Object locker = new Object();//锁
private PriorityQueue<MytimerTask> queue = new PriorityQueue<>();
通过优先队列,来对时间进行排列。
schedule
java
public void schedule(Runnable task, long delay) {
synchronized (locker) {
queue.offer(new MytimerTask(task, System.currentTimeMillis() + delay));
locker.notify();
}
}
初始化方法
java
public Mytimer() {
Thread t1 = new Thread(()->{
synchronized (locker){
try {
while (true) {
while (queue.size() == 0) {
//避免没有任务时的忙等
locker.wait();
}
if (queue.peek().time <= System.currentTimeMillis()) {
queue.peek().runnable.run();
queue.poll();
} else {
//此处也是为了避免忙等
//等待时间,虽然可能会错误唤醒,但是影响几乎可以忽略不计。
locker.wait(queue.peek().time - System.currentTimeMillis());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
}
此处的wait不能使用sleep来代替
- sleep的时候不会释放锁,到时候添加不了新的任务。
- sleep时长是固定的,如果等待时候添加了一个时间更早的任务,可能导致无法正确执行。而wait在添加新任务的时候会被唤醒一次。
感谢各位的观看Thanks♪(・ω・)ノ,如果觉得满意的话留个关注再走吧。