Netty中的时间轮(v3.10.7)

在上一篇Netty中的时间轮(v3.2.5)中,讲解的版本是v3.2.5,它在MAVEN仓库中是可以找到的.这篇文章讲解的是3.x系列中目前最高的版本v3.10.7,它在MAVEN仓库中不存在,这个版本只在Netty源码中可以找到.讲解这个v3.10.7版本的目的是要和v3.2.5版本做个对比,看它们各自在时间轮上的实现差异.

在时间轮创建的底层,v3.10.7使用的是普通对象数组,而v3.2.5使用的是集合数组.

// v3.2.5版本中的时间轮底层存放任务的结构

在v3.2.5版本中,当提交一个任务的时候,任务是直接放入到时间轮上面去的.每个格子都指向一个HashMap,HashMap中存放着提交的任务.如下图

在v3.10.7版本中,当提交一个任务的时候,并不是立刻就放到时间轮上面,而是先放到一个队列中,之后每次执行任务的时候,从队列中最多取出100000个任务放到时间轮上.

接下来从源码的角度看下v3.10.7版本的实现.代码做了删减,只体现重点.

public HashedWheelTimer(

在构造方法中,会创建时间轮,它的底层就是一个对象数组.有一个timeouts的队列,用于存储外界提交的任务.

private static final class HashedWheelBucket {

外界提交任务的时候,代码如下

public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {

时间轮执行任务,代码如下

public void run() {

上一篇文章介绍过关于startTime,deadline的含义.这里再说一下

当时间轮启动的时候,虽然startTime = System.nanoTime(). 其实我们可以换个角度,在时间轮的世界里,startTime=0,因为世界才刚刚开始启动.

当一个任务要延时delay执行的时候,它在时间轮的世界里就已经被固定好位置了.随着时间轮的'转动',当时间'走'到相应的位置,就会执行符合条件的任务.

再看下任务提交时的关于deadline的概念

public Timeout newTimeout(TimerTask task, long delay, TimeUnit unit) {

long deadline = System.nanoTime() + unit.toNanos(delay) - startTime 这行代码,它使用当前时间减去startTime时间,再加上延时时间delay.  表示的含义就是任务相对于起点(startTime那个时刻点)的位置.

关于时间轮,大家可以想象下卷尺.

时间轮在执行任务的时候,上面的代码有个waitForNextTick方法

private long waitForNextTick() {

用图形表示下上面这段代码的含义

只有当前时间currentTime等于deadline的时候,才会跳出循环.

跳出循环之后,接下来就会从任务队列中取出任务放到时间轮上.

private void transferTimeoutsToBuckets() {

最多取出100000个任务放到时间轮上.

接下来就是执行过期的任务

public void expireTimeouts(long deadline) {

会遍历每个格子中的任务,如果任务超期了,则执行它.

本文分享自微信公众号 - Netty历险记(infuq217)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )