一种超时控制的方式
版权声明:本文为本作者原创文章,转载请注明出处。感谢 码梦为生| 刘锟洋 的投稿
今天看到 这篇文章:您还有心跳吗?超时机制分析 觉得挺有意思,有兴趣的同学可以先看看他的文章,简单记录了下自己的一个想法,无论好坏,权当参与讨论,共同进步吧。
其实 lz 一直限制在了取系统时间耗时的问题上,所以,一直想变相的通过各种手法排除掉获取系统时间的逻辑,比如使用“次数”来对连接实现超时控制,但其实,使用次数来表示超时控制本身就是个伪命题, 比如,在超时次数的阀值是100,如果在90次后,就一直没有被其他线程使用,一直不到阀值,那怎么去将这个连接释放掉呢?
所以,我想到了另外一种方式解决这个问题:
首先,要明确,我认为取系统时间可以取的,但是不一定要获取连接的这个线程去做这个事情,比如交给其他线程去做,模型可能是这样:
1. 线程A 拿到连接,调用refresh方法
2.refresh方法中,将连接自己放到一个队列中,后返回。
3. 某个特殊线程S不停的去队列中拿元素,并且,将拿到的元素和拿到时刻的时间记录下,封装好交给hash环 H, H是一个类似HashMap的HASH环,只不过头尾相接。
4. Timer线程T不停的去遍历H,将超时时间大于某个阀值的连接拿掉,设置为超时连接。
不过这里需要注意到几个问题:
1. 考虑到Connection不会无限制增多,设计成环,环并不会无限制增大,所以,可行。
2. 更仔细点,可以将Connection中放一个标志位,标示是否正在使用,timer扫描时,超时间在使用状态,或者超时间不使用的连接(标准可能不同,在被使用的,可能时间要长一点。)都可以判定为超时连接
3. 因为连接数有限,所以,线程S的队列中,也不会太长(每个连接一个位子)。
4. 通过线程S的接入,将去系统时间等耗时操作从连接转移到了线程S中,提高S线程的处理速度。
5. 线程S或许还可以一次从队列中取出多个元素,统一取一次系统时间,将取出来的多个元素设置为该时间,整个操作在毫秒内完成,可以用一个时间约等于各自连接时的真正时间,降低系统时间的获取频率。
6……. 欢迎补充。
以一个线程S的代价,加快了各个连接所在线程的处理速率,值。
版权声明:本文为本作者原创文章,转载请注明出处。感谢 码梦为生| 刘锟洋 的投稿
原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 一种超时控制的方式
“伪命题”那一段,原文是在定时器线程累加计数器,所以不存在一直达不到阈值这个情况。
没错,我理解错误了,不过 ,是可以达到超时控制的目的,但是也会把正在活跃的连接杀掉。。
我说话比较直,别介意哈,我看到你指出了两次错误,结果都被否定了(一次是在原文中),如果想从讨论中,大家都得到些收获的话,我建议你还是仔细读一下原文吧,对于你刚才说的“但是也会把正在活跃的连接杀掉”,其实我后面给出的方案,是能给出这样的保证的(在评论中说到的):在一个波动的超时范围内,是不会杀掉活跃连接,也不会漏掉超时连接,波动范围是一两个定时器周期(我没去较真具体是几个了)
恩,呵呵 讨论而已,不介意,并不是说你的解决方案就不好,不是这样的,只是,我提出了另外一种思路而已,你觉得我的这个方案,是不是会是另外一种解决办法??
能给了这样一个思路,本身就是一件不错的事。不知道你假设的场景是不是跟我提到的一样,refresh是不是频繁被调用,在refresh中并发地执行队列插入动作,开销应该是挺高的,并且,极短时间内同一个连接执行两次refresh,那是不是队列里同时存在两条相同的数据?这是不是不必要呢?
无代码无真相
原文的改动是出于性能考虑
如果你的方式更好,请给出性能对比
存储connection队列是否需要锁机制?如果要的话,开销也不小呢
可以不需要锁实现,开销肯定是有的,重点在于将去系统时间的开销转移到了其他线程中去,提高了connection本身的执行效率。
用有序队列的话,数据重复本身没有问题,因为,都是单线程串行去取的,不过,插入队列开销的问题,到是可以深入了解下是不是真的有很大开销。。