博客
关于我
Java如何简单实现一个定时器
阅读量:616 次
发布时间:2019-03-13

本文共 4252 字,大约阅读时间需要 14 分钟。

什么是定时器?

它就像是一个闹钟一样,提醒你在一定时间之后该去做什么~~

前面在线程池的时候提到过两种可以执行延迟任务的方法
  • 创建一个单线程可以执行延迟任务的线程池,Executors.newSingleThreadScheduledExecutor();
  • 创建多个可以执行延迟任务的线程池,Executors.newScheduledThreadPool

用惯了Java提供的定时器,那么如何自己去简单实现一个定时器?

实现步骤(先描述再组织):

1.如何描述:首先提供一个Timer用来描述任务,其次Timer类里面要有一个时间(什么时候去执行任务)和任务
2.如何组织:提供一个worker类进行组织, 而woeker里面要提供执行方法和添加任务
3.进行调用

具体步骤

Timer类
//Timer类class Timer {       //里面有两个属性,时间+任务    long time;    Runnable runnable;//任务就是Runnable类型的,因为它里面有自带run方法,更容易执行    //赋初值    public Timer(Runnable runnable, long after) {           this.runnable = runnable;        //这里的时间,我们就定义成多长时间之后去执行任务,也就是延迟时间 = 当前时间+要延迟的时间        this.time = System.currentTimeMillis() + after;    }}
Worker类
//组织类(Worker)    class Worker {           //1.任务的扫描和执行        //如何扫描,也就是当初始化Worker的时候就创建一个线程一直去扫描任务        public Worker() {           }        //首先必须有任务,所以要写一个添加任务的方法,里面要传入任务和执行时间        public void schedule(Runnable runnable, long after) {           }    }
**完整代码**
import java.util.Date;import java.util.concurrent.PriorityBlockingQueue;//描述类(Timer)class Timer implements Comparable
{ //里面有两个属性,时间+任务 long time; Runnable runnable;//任务就是Runnable类型的,因为它里面有自带run方法,更容易执行 //赋初值 public Timer(Runnable runnable, long after) { this.runnable = runnable; //这里的时间,我们就定义成多长时间之后去执行任务,也就是延迟时间 = 当前时间+要延迟的时间 this.time = System.currentTimeMillis() + after; } //提供一个执行方法 public void run() { runnable.run(); } //优先级的排序方法 @Override public int compareTo(Timer o) { return (int) (this.time - o.time);//正序.正序的好处:把最紧急的任务排在最前面 //return (int)(o.time-this.time);//倒叙 }} //组织类(Worker) class Worker { //1.创建一个优先级队列,但是不是所有的任务都能够放进这个队列,所有我们就指定只能够存放我们Timer类里面的任务 //2.既然是一个优先级队列,那么肯定有它的优先级,也就是重写Comparable里面的compareTo()方法 PriorityBlockingQueue
priorityBlockingQueue = new PriorityBlockingQueue<>(); //创建一个锁 Object lock = new Object(); //1.任务的扫描和执行 //如何扫描,也就是当初始化Worker的时候就创建一个线程一直去扫描任务 public Worker() { Thread thread = new Thread(() -> { while (true) { //1.扫描任务,首先得要有一个容器去放任务,那就是得有优先级阻塞队列 try { //2.获取到队首的任务,而且只要扫描到第一个任务就可以得到整个队列的(任务)检查 Timer timer = priorityBlockingQueue.take(); //当拿到任务之后就判断拿到任务的时间是否小于当前时间,如果小于,那么说明这个任务达到了当前时间,可以执行 if (timer.time <= System.currentTimeMillis()) { //然后调用run方法执行该任务 timer.run(); } else { //假如拿到的是不具备执行的任务 那就将这个任务再放进阻塞队列 priorityBlockingQueue.put(timer); System.out.println("不具备执行条件"); //存在问题:如果它不具备执行条件,但是他还是会一直扫描 //解决方法:如果他不具备执行条件,那么就让它等着,知道被唤醒 synchronized (lock){ //那么等待多久呢?就是等待时间= 任务的时间-当前时间 lock.wait(timer.time - System.currentTimeMillis()); } } } catch (InterruptedException e) { e.printStackTrace(); } } }); thread.start(); } //首先必须有任务,所以要写一个添加任务的方法,里面要传入任务和执行时间 public void schedule(Runnable runnable, long after) { priorityBlockingQueue.put(new Timer(runnable, after)); synchronized (lock){ lock.notify(); } } } public class ThreadDemo32 { public static void main(String[] args) { //创建定时器 Worker worker = new Worker(); //创建一个任务 Runnable runnable = new Runnable() { @Override public void run() { //如果要执行一个循环的延迟任务 worker.schedule(this,3*1000); System.out.println("执行任务的时间:"+new Date()); } }; //查看添加任务的时间 System.out.println("添加任务的时间:"+new Date()); //添加一个任务,然后间隔3秒 worker.schedule(runnable,3*1000); } }

注意问题

在这里插入图片描述
如果想要了解更多关于定时器的,可以参考:

转载地址:http://tgtaz.baihongyu.com/

你可能感兴趣的文章
mysql 两列互转
查看>>
MySQL 中开启二进制日志(Binlog)
查看>>
MySQL 中文问题
查看>>
MySQL 中日志的面试题总结
查看>>
mysql 中的all,5分钟了解MySQL5.7中union all用法的黑科技
查看>>
Mysql 中的日期时间字符串查询
查看>>
MySQL 中锁的面试题总结
查看>>
MySQL 中随机抽样:order by rand limit 的替代方案
查看>>
MySQL 为什么需要两阶段提交?
查看>>
mysql 为某个字段的值加前缀、去掉前缀
查看>>
mysql 主从
查看>>
mysql 主从 lock_mysql 主从同步权限mysql 行锁的实现
查看>>
mysql 主从互备份_mysql互为主从实战设置详解及自动化备份(Centos7.2)
查看>>
mysql 主从关系切换
查看>>
mysql 主键重复则覆盖_数据库主键不能重复
查看>>
Mysql 优化 or
查看>>
mysql 优化器 key_mysql – 选择*和查询优化器
查看>>
MySQL 优化:Explain 执行计划详解
查看>>
Mysql 会导致锁表的语法
查看>>
mysql 使用sql文件恢复数据库
查看>>