在 JavaEE 开发中,多线程编程是一项重要的技术,定时器是一种常用的应用场景,通常用于定期执行某些任务。本文将重点介绍 Java 中的定时器的使用以及如何模拟一个简化版的定时器原码。

一、定时器的使用

Java 提供了 java.util.Timerjava.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 提供的定时器类,我们可以方便地实现定时任务;而通过手动实现,我们加深了对定时器原理的理解。这两种方式各有优缺点,开发者可以根据具体情况进行选择。在实际的应用中,还需要考虑线程安全、异常处理等问题,确保系统的稳定性与可靠性。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部