1.缘由
问题1:最近做了连拍照片功能,由于结果拍照的结果,g7并未主动推送给我们,导致需要我们主动查询获取照片url。
问题2: 目前需要支持规定时间内连续拍照,并当所有结果都收集到后,返回给调用方。
问题1解决方式: 当我们下发了拍照指令后,会将结果保存在redis当中,由于公司内部框架不持支秒级别的定时任务,所有采用spring定时器,每1秒执行一次,去遍历redis,获取到结果后便清除。
问题2解决方式: 利用两次Redis zset,第一次借助spring定时器,获取到期的集合,并发起拍照指令。另一个zset则存放获取到的结果,当达到指定次数后,就统一将结果返回给调用方。
问题2定时触发没有利用rabbitMq的延时机制,因为公司内部基本采用kafka。所以也并没去临时申请。延时队列没有持久化,所以也没有考虑。
种种缘由,导致这单单一个功能就利用到了两个定时器,并且一个定时器启用一个线程,那么公司内部那么多处使用。这一定程度上对资源造成了很大的浪费。
2.通过上诉的问题,突然想到这不就是select模型吗?那么是否能转换成epoll模型呢?
1、int epoll_create(int size) 创建一个epoll句柄,参数size用来告诉内核监听的数目。
2、int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
3、 int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
等待事件的产生,类似于select()调用。参数events用来从内核得到事件的集合,maxevents告之内核这个events有多大,这个maxevents的值不能大于创建epoll_create()时的size,参数timeout是超时时间(毫秒,0会立即返回,-1将不确定,也有说法说是永久阻塞)。该函数返回需要处理的事件数目,如返回0表示已超时。
开始看到有一个wait,还蛮惊喜以为可以达到延时的作用,后来仔细阅读并没有这个作用。
继续延申
如果epoll命令起不到这样的作用,那么NIO模型里面采用到了这个模型,是否可以借用这个模型去达到想要的效果呢。于是便查询NIO模型的实现方式,发现对于数据的解析api很繁琐。
继续延申
那么一下子想到了netty模型是对这个NIO的很好实现,便带着期待查询 netty是否包含延时机制。
眼前一亮,果然有相应的算法HashedWheelTimer 时间伦算法,那这个api一定不错,便查询了一下是这么介绍的。
时间轮是一种非常惊艳的数据结构。其在Linux内核中使用广泛,是Linux内核定时器的实现方法和基础之一。
换句话说时间轮是一种高效来利用线程资源来进行批量化调度的一种调度模型。把大批量的调度任务全部都绑定到同一个的调度器上面,使用这一个调度器来进行所有任务的管理(manager),触发(trigger)以及运行(runnable)。能够高效的管理各种延时任务,周期任务,通知任务等等其实笔者认为其最大的优点就是可以在一个线程中动态的添加定时(延时)任务
像我们经常使用Timer,ScheduledExecutorService,Spring的Scheduled这些都是无法做到这一点的,一旦某个线程开始执行某个定时任务,都是无法再去动态添加的
那某些场景,比如说有很多小的定时任务,难道每一个都去起一个线程处理吗?那数量多的话对程序势必影响很大,浪费资源,这个时候就可以考虑HashedWheelTimer了.
正好派上用场。