在 JavaEE 开发中,多线程编程是一项重要的技术,定时器是一种常用的应用场景,通常用于定期执行某些任务。本文将重点介绍 Java 中的定时器的使用以及如何模拟一个简化版的定时器原码。
一、定时器的使用
Java 提供了 java.util.Timer
和 java.util.TimerTask
类来便捷地处理定时任务。Timer
类用于调度任务,而 TimerTask
则是要被调度的具体任务。
1.1 定时器基本用法
下面是一个简单的示例,该示例每秒打印一次当前时间:
import java.util.Timer;
import java.util.TimerTask;
import java.text.SimpleDateFormat;
import java.util.Date;
public class TimerExample {
public static void main(String[] args) {
Timer timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println("当前时间: " + sdf.format(new Date()));
}
};
// 每隔1秒执行一次
timer.schedule(task, 0, 1000);
// 主线程休眠10秒后取消定时器
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
timer.cancel();
System.out.println("定时器已取消");
}
}
}
在这个示例中,我们创建了一个定时器 Timer
,然后通过 schedule
方法每隔一秒执行一次 task
。主线程在10秒后停止并取消定时器。
二、定时器的内部原码模拟
为了更深入理解定时器的工作原理,我们可以尝试手动实现一个简化版的定时器。这种实现方式主要包括一个线程用于执行定时任务、一个任务列表来存储待执行的任务。
2.1 自定义定时器
以下是我们的自定义定时器的实现:
import java.util.*;
import java.util.concurrent.TimeUnit;
public class MyTimer {
private final List<ScheduledTask> tasks = new ArrayList<>();
private boolean isRunning = false;
public void schedule(Runnable task, long delay, long period) {
ScheduledTask scheduledTask = new ScheduledTask(task, delay, period);
tasks.add(scheduledTask);
if (!isRunning) {
isRunning = true;
new Thread(this::run).start();
}
}
private void run() {
while (isRunning) {
long currentTime = System.currentTimeMillis();
for (ScheduledTask scheduledTask : tasks) {
scheduledTask.execute(currentTime);
}
try {
Thread.sleep(100); // 每100毫秒检查一次
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void cancel() {
isRunning = false;
}
private static class ScheduledTask {
private final Runnable task;
private final long period;
private long nextRunTime;
public ScheduledTask(Runnable task, long delay, long period) {
this.task = task;
this.period = period;
this.nextRunTime = System.currentTimeMillis() + delay;
}
public void execute(long currentTime) {
if (currentTime >= nextRunTime) {
task.run();
nextRunTime += period; // 更新下次运行时间
}
}
}
public static void main(String[] args) {
MyTimer myTimer = new MyTimer();
myTimer.schedule(() -> {
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
System.out.println("自定义定时器任务执行: " + sdf.format(new Date()));
}, 0, 1000); // 初始延迟为0,周期为1秒
try {
Thread.sleep(10000); // 让定时器运行10秒
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
myTimer.cancel(); // 取消定时器
System.out.println("自定义定时器已取消");
}
}
}
2.2 实现说明
在这个简化的版本中,我们创建了一个 MyTimer
类:
- schedule
方法用于添加定时任务。
- run
方法在一个独立的线程中循环检查是否有任务需要执行。
- ScheduledTask
是每个任务的封装,包含了任务的执行逻辑和下次执行的时间。
总结
通过 Java 提供的定时器类,我们可以方便地实现定时任务;而通过手动实现,我们加深了对定时器原理的理解。这两种方式各有优缺点,开发者可以根据具体情况进行选择。在实际的应用中,还需要考虑线程安全、异常处理等问题,确保系统的稳定性与可靠性。