【发布时间】:2010-10-01 19:12:06
【问题描述】:
更新:这里是my implementation of Hashed Timing Wheels。如果您有提高性能和并发性的想法,请告诉我。 (2009 年 1 月 20 日)
// Sample usage:
public static void main(String[] args) throws Exception {
Timer timer = new HashedWheelTimer();
for (int i = 0; i < 100000; i ++) {
timer.newTimeout(new TimerTask() {
public void run(Timeout timeout) throws Exception {
// Extend another second.
timeout.extend();
}
}, 1000, TimeUnit.MILLISECONDS);
}
}
更新:我通过使用Hierarchical and Hashed Timing Wheels 解决了这个问题。 (2009 年 1 月 19 日)
我正在尝试在 Java 中实现一个特殊用途的计时器,该计时器针对超时处理进行了优化。例如,用户可以注册一个带有截止期限的任务,并且计时器可以在截止期限结束时通知用户的回调方法。在大多数情况下,注册的任务会在很短的时间内完成,因此大多数任务将被取消(例如 task.cancel())或重新安排到未来(例如 task.rescheduleToLater(1, TimeUnit.SECOND)) .
我想用这个定时器来检测一个空闲的socket连接(比如10秒内没有收到消息时关闭连接)和写超时(比如30秒内写操作没有完成时引发异常)。大多数情况下,不会发生超时,客户端会发送消息并发送响应,除非出现奇怪的网络问题..
我不能使用 java.util.Timer 或 java.util.concurrent.ScheduledThreadPoolExecutor 因为他们认为大多数任务都应该超时。如果一个任务被取消,被取消的任务被存储在它的内部堆中,直到 ScheduledThreadPoolExecutor.purge() 被调用,这是一个非常昂贵的操作。 (也许是 O(NlogN)?)
在我在 CS 课程中学到的传统堆或优先级队列中,更新元素的优先级在许多情况下是一项昂贵的操作(O(logN)),因为它只能通过删除元素并重新插入来实现它具有新的优先级值。像斐波那契堆这样的堆有 O(1) 时间的 reductionKey() 和 min() 操作,但我至少需要快速 increaseKey() 和 min() (或 reductionKey() 和 max ())。
您知道针对此特定用例高度优化的任何数据结构吗?我正在考虑的一种策略是将所有任务存储在哈希表中,并每秒左右迭代所有任务,但这并不是那么漂亮。
【问题讨论】:
-
为什么 O(LogN) 更新会太慢?
-
因为更新会非常非常频繁。假设我们每个连接发送 M 条消息,那么总时间变成 O(MNlogN),这是相当大的。
-
我无法清楚地理解您的问题。能改一下吗?
-
来自未来的更新:“我的 Hashed Timing Wheels 的实现”的链接已损坏。这真的太糟糕了,因为它本来可以解决我的问题。
标签: data-structures timeout queue scheduling priority-queue