Java定时器的实现(MyTimer)

文章讨论了如何使用Java实现一个定时器,包括维护一个优先级队列来存储任务,一个线程持续检查并执行到期的任务。同时,提到了线程安全问题,如可能的遗漏通知和忙等现象,并给出了一段示例代码来说明解决这些问题的方法。
摘要由CSDN通过智能技术生成

首先我们要清楚 实现定时器的话我们需要定时器有哪些功能?

        1.有一个优先级队列存放要执行的任务(什么样的优先级?需要我们自己规定)

        2.有一个线程不断检查任务是否到时间需要执行了,时间到了执行,时间没到再放回到队列里,继续检查。

        3.可以注册任务,并且能存放进优先级队列

这里我们必须注意的问题:

        两个线程之间读和放,有可能造成线程安全问题

        在每次存放之后有一个极端情况,在上一个任务被判定时间不到的时间内,放一个新的任务之后线程立即调度走,可能遗漏这个线程的通知,导致这个任务无法被提醒

由于扫描线程一直在检查,可能,会出现忙等现象,造成CPU资源浪费。

下面附上一个实现的定时器案例,配上详细的注释,希望对你的学习有所帮助。

import java.util.concurrent.PriorityBlockingQueue;

public class ThreadDemo10 {
    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("时间到了,执行!");
            }
        },3000);
        System.out.println("执行之前。");}

}
//定时器         定时器内部能够存放多个任务,需要考虑到线程安全问题  还有一个专门的线程来取任务
class MyTimer {
    private  Object locker = new Object();
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<MyTask>();
//schedule 方法注册任务 然后存放到队列中
    public void schedule(Runnable runnable, long delay) {
    MyTask task = new MyTask(runnable,delay);
    queue.put(task);
    //每次插入之后都要唤醒一下扫描线程,防止遗漏
        synchronized (locker){
            locker.notify();
        }
    }

    //创建一个扫描线程
    public MyTimer(){
        Thread t1 = new Thread(()->{
          //一直不断地扫描
            while(true){
                try {
                    MyTask task = queue.take();
                    long curTime = System.currentTimeMillis();
                    //比较一下时间到了吗
                    if(curTime < task.getTime()){
                        //时间没到,塞回去。
                        queue.put(task);
                        //再在这里设置一个等待时间
                        synchronized (locker){
                            //等待时间到了唤醒
                            // 这里的wait是指的最大时间,在这个时间内 如果有notify的话 线程会继续执行,再次检查一遍。
                            locker.wait(task.getTime()-curTime);
                        }
                    } else{
                        //时间到了执行
                            task.run();
                        }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        t1.start();
    }
}

class MyTask implements Comparable<MyTask> {
    //实现comparable接口 让程序以某种规则来可以进行比较
//任务需要干啥
    private Runnable runnable;
    //任务啥时间干 保存任务要执行的毫秒级时间戳
    private long time;

    //提供一个构造方法
    public MyTask(Runnable runnable, long delay) {
        this.runnable = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

    public void run() {
        runnable.run();
    }

    public long getTime() {
        return time;
    }

    @Override
    public int compareTo(MyTask o) {
        //这里实现让小的在前大的在后。
        return (int) (this.time - o.time);

    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值