目录
1.前言
哈喽大家好呀,今天继续给大家分享Java中定时器的学习,正文包括定时器的三种实现方式,正文如下。
2.正文
在 Java 中,定时器(Timer)是一种用于在指定时间或周期性地执行任务的工具。Java 提供了多种定时器实现方式,包括 Timer
和 TimerTask
、ScheduledExecutorService。
2.1库中定时器
最基础版的实现方式:
public static void main(String[] args) {
Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 3000");
}
}, 3000);
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("hello 1000");
}
}, 1000);
}
执行流程
创建Timer实例:
Timer timer = new Timer()
创建一个新的定时器Timer内部会启动一个后台线程(非守护线程)来执行定时任务
调度第一个任务:
延迟3000毫秒后执行,输出"hello 3000"
任务被封装为TimerTask对象
调度第二个任务:
延迟1000毫秒后执行,输出"hello 1000"
虽然代码中先注册了3000ms的任务,但实际会先执行1000ms的任务
关键特性
执行顺序:
Timer内部维护了一个任务队列,按执行时间排序
即使先注册长时间延迟的任务,短延迟的任务也会优先执行
单线程执行:
所有任务都在同一个线程中顺序执行
如果一个任务执行时间过长,会影响后续任务的准时执行
非守护线程:
Timer创建的线程是非守护线程
即使main方法结束,Timer线程仍会继续运行,直到所有任务完成
进阶版利用线程池实现定时器:
public static void main(String[] args) {
// 1. 创建线程池大小为3的定时任务执行器
ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
// 2. 定义要执行的任务(Lambda表达式实现Runnable接口)
Runnable task = () -> {
System.out.println(Thread.currentThread().getName());
};
// 3. 以固定速率调度任务
executor.scheduleAtFixedRate(task, 1, 3, TimeUnit.SECONDS);
}
核心组件详解
1. ScheduledExecutorService
功能:Java 5引入的定时任务接口,比传统Timer更强大
优势:
基于线程池,支持多任务并发执行
提供更灵活的调度方式
更好的异常处理机制
2. Executors.newScheduledThreadPool(3)
创建包含3个线程的定时任务线程池
线程池参数说明:
核心线程数=3(本例中)
适合执行大量短期定时任务
线程可重复利用,避免频繁创建销毁开销
3. scheduleAtFixedRate方法
方法签名:
ScheduledFuture<?> scheduleAtFixedRate( Runnable command, long initialDelay, long period, TimeUnit unit )
参数说明:
command
:要执行的任务(Runnable实现)
initialDelay
:首次执行的延迟时间
period
:连续执行之间的周期
unit
:时间单位(本例为秒)
执行流程分析
初始化阶段:
创建包含3个工作线程的线程池
定义打印当前线程名的任务
任务调度:
1秒后首次执行任务
之后每3秒固定执行一次
执行线程可能不同(由线程池分配)
输出示例:
pool-1-thread-1 pool-1-thread-2 pool-1-thread-3 pool-1-thread-1 ...
2.2手搓定时器
分为三个类:任务类,定时器类,测试类最后附上总代码:
/**
* 自定义定时任务类,实现了Comparable接口用于优先级队列排序
*/
class MyTimerTask implements Comparable<MyTimerTask> {
private Runnable task; // 实际要执行的任务
private long time; // 任务执行的时间戳(毫秒)
/**
* 构造函数
* @param task 要执行的任务
* @param delay 延迟时间(毫秒)
*/
public MyTimerTask(Runnable task, long delay) {
this.task = task;
this.time = System.currentTimeMillis() + delay; // 计算绝对执行时间
}
/**
* 实现Comparable接口,用于优先级队列排序
* @param o 另一个定时任务
* @return 比较结果
*/
@Override
public int compareTo(MyTimerTask o) {
return (int) (this.time - o.time); // 按执行时间排序
}
/**
* 获取任务执行时间
* @return 执行时间戳
*/
public long getTime() {
return this.time;
}
/**
* 执行任务
*/
public void run() {
task.run(); // 委托给实际的Runnable执行
}
}
/**
* 自定义定时器实现
*/
class MyTimer {
// 优先级队列,按执行时间排序,保证最早执行的任务在队首
private PriorityQueue<MyTimerTask> queue = new PriorityQueue<>();
// 用于线程同步的锁对象
private Object locker = new Object();
/**
* 调度任务方法
* @param task 要执行的任务
* @param delay 延迟时间(毫秒)
*/
public void schedule(Runnable task, long delay) {
synchronized (locker) {
// 创建定时任务并加入队列
MyTimerTask myTimerTask = new MyTimerTask(task, delay);
queue.offer(myTimerTask);
// 通知工作线程有新任务加入
locker.notify();
}
}
/**
* 定时器构造函数
*/
public MyTimer() {
// 创建工作线程
Thread t = new Thread(() -> {
try {
while (true) { // 无限循环处理任务
synchronized (locker) {
// 队列为空时等待
while (queue.isEmpty()) {
locker.wait();
}
// 获取但不移除队首任务
MyTimerTask task = queue.peek();
long currentTime = System.currentTimeMillis();
if (currentTime < task.getTime()) {
// 还未到执行时间,等待剩余时间
locker.wait(task.getTime() - currentTime);
} else {
// 执行任务并从队列移除
task.run();
queue.poll();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start(); // 启动工作线程
}
}
/**
* 定时器测试类
*/
public class demoTime {
public static void main(String[] args) {
MyTimer timer = new MyTimer(); // 创建定时器
// 添加3个定时任务
timer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("hello 3000");
}
}, 3000); // 3秒后执行
timer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("hello 2000");
}
}, 2000); // 2秒后执行
timer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("hello 1000");
}
}, 1000); // 1秒后执行
}
}
import java.util.PriorityQueue;
class MyTimerTask implements Comparable<MyTimerTask>{
private Runnable task;
private long time;
public MyTimerTask(Runnable task, long time) {
this.task = task;
this.time = time;
}
@Override
public int compareTo(MyTimerTask o) {
return (int) (this.time - o.time);
}
public long getTime(){
return this.time;
}
public void run(){
task.run();
}
}
class MyTimer{
private PriorityQueue <MyTimerTask> queue = new PriorityQueue<>();
private Object locker = new Object();
public void schedule(Runnable task,long delay){
synchronized (locker){
MyTimerTask myTimerTask = new MyTimerTask(task,System.currentTimeMillis() + delay);
queue.offer(myTimerTask);
locker.notify();
}
}
public MyTimer(){
Thread t = new Thread(()-> {
try {
while (true) {
synchronized (locker) {
while (queue.isEmpty()) {
locker.wait();
}
MyTimerTask task = queue.peek();
if (System.currentTimeMillis() < task.getTime()) {
locker.wait(task.getTime() - System.currentTimeMillis());
} else {
task.run();
queue.poll();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t.start();
}
}
public class demoTime {
public static void main(String[] args) {
MyTimer timer = new MyTimer();
timer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("hello 3000");
}
}, 3000);
timer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("hello 2000");
}
}, 2000);
timer.schedule(new Runnable() {
@Override
public void run() {
System.out.println("hello 1000");
}
}, 1000);
}
}
3.小结
今天的分享到这里就结束了,喜欢的小伙伴点点赞点点关注,你的支持就是对我最大的鼓励,大家加油!