Java中的Timer类以及自己实现一个MyTimer

本文详细介绍了Java中的Timer类,包括其任务调度、单线程特性、多任务支持、异常处理以及与ScheduledThreadPoolExecutor的比较。还提供了自定义MyTimer类的示例。
摘要由CSDN通过智能技术生成

Timer 类是 Java 提供的用于执行定时任务的工具类。它允许你安排任务在未来的某个时间点执行,也可以定期执行。下面是关于Timer类的详细介绍:

一、主要特点

  1. 任务调度Timer 类允许你调度指定的任务在将来的某个时间执行,或者按照一定的时间间隔循环执行。

  2. 单线程执行任务Timer 内部维护一个后台线程,用于执行任务。这意味着所有任务都是由同一个线程来串行执行的,因此如果一个任务执行时间过长,会影响其他任务的执行。

  3. 多任务支持Timer 允许你安排多个任务执行。

  4. 异常处理Timer 会捕获任务抛出的未捕获异常,防止这些异常中断任务队列的执行流程。

二、应用场景

  • 定时任务调度:适用于需要在特定时间执行任务的场景,比如定时数据备份、定时数据清理等。

  • 定期任务执行:适用于需要按照一定的时间间隔重复执行任务的场景,如定时发送心跳、定期执行某些操作等。

三、基本用法

要使用Timer类执行定时任务,通常需要创建一个继承自TimerTask类的任务,并在Timer对象中安排任务的执行时间。例如:

import java.util.Timer;
import java.util.TimerTask;

public class ScheduledTask extends TimerTask {
    @Override
    public void run() {
        System.out.println("Task executed at: " + System.currentTimeMillis());
    }

    public static void main(String[] args) {
        Timer timer = new Timer();
        long delay = 1000; // 任务延迟1秒执行
        long interval = 2000; // 任务每隔2秒执行一次
        timer.scheduleAtFixedRate(new ScheduledTask(), delay, interval);
    }
}

注意事项

  • 线程安全性:由于Timer是基于单个后台线程执行任务的,需要注意任务执行时间过长可能会影响其他任务的执行。

  • 异常处理:需要留意捕获任务抛出的异常,以免异常中断任务队列的执行流程。

  • Java 5 之后的替代方案:虽然Timer类已经存在很长时间,但在 Java 5 中ScheduledThreadPoolExecutor被引入,通常被认为是Timer的更灵活、更可控制的替代方案。

四、自己实现

import java.util.PriorityQueue;

public class MyTimer {
    //内部类表示创建的任务
    class Mytask implements Comparable<Mytask> {
        private Runnable runnable;
        // 为了⽅便后续判定, 使⽤绝对的时间戳.
        private long time;

        public Mytask(Runnable runnable, long delay) {
            this.runnable = runnable;
            // 取当前时刻的时间戳 + delay, 作为该任务实际执⾏的时间戳
            this.time =  System.currentTimeMillis() + delay;
        }

        //表示每个任务以到达时间以小到大排序
        // 这样的写法意味着每次取出的是时间最⼩的元素.
        @Override
        public int compareTo(Mytask o) {
            return (int)(this.time - o.time);
        }
    }
    // 核⼼结构
    private PriorityQueue<Mytask> queue = new PriorityQueue<>();
    // 创建⼀个锁对象
    private Object locker = new Object();

    //构造方法,创建线程
    Thread t;
    public MyTimer() {
        // 在这⾥构造线程, 负责执⾏具体任务了.
        t = new Thread( () -> {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    synchronized (locker) {
                        // 阻塞队列, 只有阻塞的⼊队列和阻塞的出队列, 没有阻塞的查看队⾸元素
                        while (queue.isEmpty()) {
                            locker.wait();
                        }
                        Mytask task = queue.peek();
                        long waitTime = task.time - System.currentTimeMillis();
                        if (waitTime <= 0) {
                            // 时间到了, 可以执⾏任务了
                            queue.poll();
                            task.runnable.run();
                        } else {
                            // 时间还没到
                            locker.wait(waitTime);
                        }
                    }
                }
            }catch (InterruptedException e) {
                    e.printStackTrace();
            }
        });
        t.start();
    }


    public void schedule(Runnable command, long after) {
        synchronized (locker) {
            Mytask mytack = new Mytask(command, after);
            //根据参数,插入队列
            queue.offer(mytack);
            locker.notify();
        }
    }

    //中断线程
    public void cancel() {
        t.interrupt();
        for (Mytask task : queue) {
            queue.remove(task);
        }
    }


    // 测试代码
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule( ()->{
            System.out.println(2000);
        }, 2000);
        timer.schedule( () -> {
            System.out.println(1000);
        }, 1000);
        timer.schedule( ()->{
            System.out.println(3000);
        }, 3000);

        System.out.println(100);

    }
}

 

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值