Java多线程之手动实现定时器(Timer)

定时器

  • 我们先来说要实现一个定时器都需要什么东西
  1. 保存待执行任务的优先级阻塞队列
  2. 描述任务的任务类
  3. 扫描队列头是否达到执行时间的扫描线程

我们先写一个Task任务类

class Task implements Comparable<Task>{
        private Runnable command  = null;
        private long time = 0;

        public Task(Runnable command, long time) {
            this.command = command;
            this.time = time+System.currentTimeMillis(); //表示任务将要在什么时间执行
        }
        //执行任务的方法
        public void run(){
            command.run();
        }

        @Override
        public int compareTo(Task o) {   //实现comparable接口用任务执行时间先后作为优先级的的判断条件
            return (int)(this.time - o.time);
        }
    }

然后写一个Worker扫描线程

//创建扫描工具类
    class Worker extends Thread{
        @Override
        public void run() {
            while (true){
                try {
                    synchronized (this) {
                        Task task = queue.take();
                        long nowTime = System.currentTimeMillis();
                        if(task.time > nowTime){ //把优先级最高的任务取出来,判断任务是否达到执行条件
                            queue.put(task);     //如果没有就把任务放回去,让扫描等待当前时间和任务执行时间时间差后再次进行判断扫描
                            wait(task.time - nowTime);
                        }
                        else{
                            task.run();
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

接下来我们将定时器类进行完善 写出完整代码

public class Timer  {
    // 保存待执行任务的优先级阻塞队列
    private PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<>();
    //描述任务的类
    class Task implements Comparable<Task>{
        private Runnable command  = null;
        private long time = 0;

        public Task(Runnable command, long time) {
            this.command = command;
            this.time = time + System.currentTimeMillis();
        }
        //执行任务的方法
        public void run(){
            command.run();
        }

        @Override
        public int compareTo(Task o) {
            return (int)(this.time - o.time);
        }
    }
    //创建扫描工具类
    class Worker extends Thread{
        @Override
        public void run() {
            while (true){
                try {
                    synchronized (this) {
                        Task task = queue.take();
                        long nowTime = System.currentTimeMillis();
                        if(task.time > nowTime){ //把优先级最高的任务取出来,判断任务是否达到执行条件
                            queue.put(task);     //如果没有就把任务放回去,让扫描等待当前时间和任务执行时间时间差后再次进行判断扫描
                            wait(task.time - nowTime);
                        }
                        else{
                            task.run();
                        }
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public Timer() {
        Worker worker = new Worker();  //当创建定时器类对象的时候就会启动worker扫描线程
        worker.start();
    }

    public void insert(Runnable runnable, long time ){  //向定时器任务队列中添加待执行任务
        Task task  = new Task(runnable,time);
        queue.put(task);
        synchronized (this) {
            notify();  //此处掉用notify是为了防止有新的任务加入之后,新的任务优先度高于之前队头元素优先度
                      //所以此处调用notify唤醒扫描线程,重新判断优先度最高的任务是否达到执行条件
        }
    }

最后我们创建一个main方法测试定时器功能

public static void main(String[] args) {
        Timer timer = new Timer();
        Runnable r = new Runnable() {
            @Override
            public void run() {
                System.out.println("闹钟响了");
            }
        };
        System.out.println("开始计时:");
        timer.insert(r,3000);
    }
  • 其实这个定时器中的一个关键点就是利用的wait方法和notify方法和优先级阻塞队列,防止了线程进行无意义的扫描;
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值