Java多线程~认识并手动实现一个定时器

目录

定时器

标准库中的定时器

定时器的使用

实现一个定时器

定时器的构成

核心接口schedule

mailBox对象 

 扫描器worker线程

完整代码

代码测试 


定时器

定时器是软件开发中的一个重要组件,类似于一个闹钟,达到一个特定时间后,就执行某个指定好的代码。

标准库中的定时器

· 标准库提供了一个Timer类,Timer类的核心方法为schedule.

· schedule方法包含两个参数,第一个参数指定将要执行的任务代码,第二个参数指定多长时间后执行这段代码(单位为毫秒).

定时器的使用

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

public class TimerTest {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("Hello");
            }
        },3000);
    }
}

上述代码的意思为TimerTask对象为所要执行的任务代码,指定为输出"Hello",后面的3000为指定的时间,即程序运行3000毫秒后执行这段代码 .

运行结果

实现一个定时器

定时器的构成

· 一个带优先级的阻塞队列

因为阻塞队列中的任务都有各自的执行时刻,最先执行的任务一定是执行时刻最小的任务。使用带优先级的优先队列就可以高效的把执行时刻最小的这个任务找出来.

· 队列中的每一个元素是一个Task对象

· Task中带有一个时间属性,队首元素就是即将执行的元素

· 同时有一个work线程一直扫描队首元素,看队首元素是否需要执行

核心接口schedule

Timer类提供的核心接口就是schedule接口,用于注册一个任务,并指定这个任务多长时间后执行

    public void schedule(Runnable command, long after) {
        Task task = new Task(command,after);
        queue.offer(task);
        synchronized(mailBox) {
            mailBox.notify();
        }
    }

mailBox对象 

mailBox对象是定时器中非常重要的一个成员,可以借助该对象的wait和notify来解决while(true)的忙等问题,具体应用在下方扫描器woker中

    //避免worker线程出现忙等的情况
    private Object mailBox = new Object();

 扫描器worker线程

woker线程的作用是扫描队首元素,看其是否能够执行这个任务,如果不利用mailBox对象的wait方法,woker线程就会一直扫描阻塞队列队首位置,一秒钟扫描几万次,但在加上mailBox对象的wait方法后就可以解决这个忙等的问题了

public class MyTimer {

    class Worker extends Thread {
        @Override
        public void run() {
            while(true) {
                try {
                    Task task = queue.take();
                    long curTime = System.currentTimeMillis();
                    if(task.time > curTime) {
                        //如果执行时间还未到,就将任务重新放入阻塞队列中
                        queue.put(task);
                        synchronized (mailBox) {
                            //指定等待时间
                            mailBox.wait(task.time - curTime);
                        }
                    }else {
                        //时间如果到了就执行任务
                        task.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public MyTimer() {
        //启动work线程
        Worker worker = new Worker();
        worker.start();
    }
}

完整代码

import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description: 实现一个定时器
 * User: Li_yizYa
 * Date: 2022—05—24
 * Time: 15:54
 */
public class MyTimer {
    static class Task implements Comparable<Task> {
        private Runnable command;
        private long time;
        public Task(Runnable command, long time) {
            this.command = command;
            //time中存的是绝对时间,超过这个时间任务就需要被执行
            this.time = System.currentTimeMillis() + time;
        }

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

        @Override
        public int compareTo(Task o) {
            //谁的时间小谁排在前面
            return (int)(time - o.time);
        }
    }

    //核心结构: 一个带优先级的阻塞队列
    private PriorityBlockingQueue<Task> queue = new PriorityBlockingQueue<>();
    //避免worker线程出现忙等的情况
    private Object mailBox = new Object();

    class Worker extends Thread {
        @Override
        public void run() {
            while(true) {
                try {
                    Task task = queue.take();
                    long curTime = System.currentTimeMillis();
                    if(task.time > curTime) {
                        //如果执行时间还未到,就将任务重新放入阻塞队列中
                        queue.put(task);
                        synchronized (mailBox) {
                            //指定等待时间
                            mailBox.wait(task.time - curTime);
                        }
                    }else {
                        //时间如果到了就执行任务
                        task.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    public MyTimer() {
        //启动work线程
        Worker worker = new Worker();
        worker.start();
    }
    //schedule
    public void schedule(Runnable command, long after) {
        Task task = new Task(command,after);
        queue.offer(task);
        synchronized(mailBox) {
            mailBox.notify();
        }
    }
}

代码测试 

class MyTimerTest {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        Runnable command = new Runnable() {
            @Override
            public void run() {
                System.out.println("我来了");
                timer.schedule(this,3000);
            }
        };
        timer.schedule(command,3000);
    }
}

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Li_yizYa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值