Timer 是 Java 提供的一个简单的任务调度工具(位于 java.util 包),用于在指定的时间执行任务(一次性或周期性执行)。
定时任务:在指定的延迟后执行一次任务。
周期性任务:按照固定的时间间隔重复执行任务
方法 | 说明 |
|---|---|
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,取消所有已安排的任务 |
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秒后执行
}
} Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 1000");
}
}, 1000, 1000); // 每隔1s执行一次 单线程执行:所有任务都在同一个线程中执行,如果一个任务执行时间过长,会影响其他任务的调度。
异常影响全局:如果某个任务抛出未捕获的异常,整个 Timer 会终止,后续任务不会执行。
时间精度依赖系统时钟:如果系统时间被调整(如手动修改时间),可能导致任务执行不准确。
由于 Timer 的局限性,Java 5 引入了
ScheduledExecutorService(属于 java.util.concurrent 包),它使用线程池,更稳定、更灵活,推荐在新代码中使用。
使用线程池的工厂类
创建单线程的ScheduledExecutorService,任务量少,需顺序执行
Executors.newSingleThreadScheduledExecutor()
创建n个线程的ScheduledExecutorService,高并发任务,需并行执行
Executors.newScheduledThreadPool(n)
创建n个线程的ScheduledExecutorService,并设置拒绝方法
Executors。ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory)直接创建
可以设置工厂方法,拒绝方法,以及核心数目
ScheduledThreadPoolExecutor(int corePoolSize, ThreadFactory threadFactory, RejectedExecutionHandler handler)推荐使用
使用 ScheduledExecutorService 进行任务调度时,可以通过不同的方法设置任务的执行方式,主要包括 延迟执行、固定速率执行 和 固定延迟执行。
参数:
schedule(Runnable command, long delay, TimeUnit unit)特点:
使用场景:只需要在某个时间点执行一次的任务(如延迟初始化、超时任务)。
示例:
executor.schedule(() -> {
System.out.println("Task runs after 3 seconds");
}, 3, TimeUnit.SECONDS);参数:
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)特点:
使用场景:适用于 严格周期性的任务(如定时数据同步)。
示例:
// 初始延迟 1 秒,之后每 2 秒执行一次(不管任务执行多久)
executor.scheduleAtFixedRate(() -> {
System.out.println("Fixed Rate Task - " + System.currentTimeMillis());
}, 1, 2, TimeUnit.SECONDS);参数:
scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)特点:
使用场景:适用于 需要保证任务执行间隔 的场景(如心跳检测)
示例:
// 初始延迟 1 秒,每次任务结束后等 2 秒再执行下一次
executor.scheduleWithFixedDelay(() -> {
System.out.println("Fixed Delay Task - " + System.currentTimeMillis());
}, 1, 2, TimeUnit.SECONDS);参数
Object locker = new Object();//锁
private PriorityQueue<MytimerTask> queue = new PriorityQueue<>();通过优先队列,来对时间进行排列。
schedule
public void schedule(Runnable task, long delay) {
synchronized (locker) {
queue.offer(new MytimerTask(task, System.currentTimeMillis() + delay));
locker.notify();
}
}初始化方法
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来代替
感谢各位的观看Thanks♪(・ω・)ノ,如果觉得满意的话留个关注再走吧。