定时器的实现

public class Test1 {

//优先队列中的元素必须是可比较的
//比较规则的指定主要是两种方式
//1.让Task实现Comparable接口
//2.让优先级队列构造的时候,传入一个比较器对象(Comparator)
static class Task implements Comparable<Task>{
    //Runnable 中有一个run方法,就可以借助这个run方法来描述要执行的具体任务是啥
    private Runnable command;
    //time 表示啥时候来执行command,是一个绝对时间(ms级别的时间戳)
    private long time;

    //构造方法的参数表示:多少毫秒之后执行(相对时间)
    public Task(Runnable command, long after) {
        this.command = command;
        this.time = System.currentTimeMillis() + after;
    }

    //执行任务的具体逻辑
    public void run(){
        command.run();
    }

    @Override
    public int compareTo(Task o) {
        //谁的时间小先执行谁
        return (int) (this.time - o.time);
    }
}



//扫描线程的逻辑
static class Worker extends Thread{
    private PriorityBlockingQueue<Task> queue = null;
    private Object mailBox = null;

    public Worker(PriorityBlockingQueue<Task> queue,Object mailBox){
        this.queue = queue;
        this.mailBox  = mailBox;
    }

    @Override
    public void run() {
        //实现具体的线程执行内容
        while (true) {
            try {
                //1.取出队首元素,检查时间是否到
                Task task = queue.take();
                //2.检查当前任务时间是否到了
                long curTime = System.currentTimeMillis();
                if (task.time > curTime){
                    //时间还没到,就把当前任务再放回队列中
                    queue.put(task);
                    //解决忙等,扫描线程内部加wait
                    synchronized (mailBox){
                        //等待的是相差的时间
                        mailBox.wait(task.time - curTime);
                    }
                }else {
                    task.run();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
                break;
            }
        }
    }
}

static class Timer{
    //为了避免忙等,需要使用wait方法
    //使用一个单独的对象辅助进行wait
    //使用this也可以
    private Object mailBox = new Object();

    //定时器的基本构成,有三部分
    //1.用一个类来描述"任务"
    //2.用一个阻塞优先队列来组织若干个任务,让队首元素就是时间最早的任务,
    // 如果队首元素时间未到,那么其他元素也肯定比態执行
    private PriorityBlockingQueue<Task>  queue = new PriorityBlockingQueue<>();
    //3.用一个线程来循环扫描当前阻塞优先队列的队首元素,如果时间到,就执行指定的任务
    public Timer(){
        Worker worker = new Worker(queue,mailBox);
        worker.start();
    }
    //4.还需要提供一个方法,让调用者能把任务给安排进去
    public void schedule(Runnable command, long after){
        Task task = new Task(command, after);
        queue.put(task);
        //解决忙等 在安排方法中加上notify
        synchronized (mailBox){
            mailBox.notify();
        }
    }
}


public static void main(String[] args) {
    Timer timer = new Timer();
    timer.schedule(new Runnable() {
        @Override
        public void run() {
            System.out.println("hehe");
            timer.schedule(this,2000);
        }
    },5000);
}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值