更新:这是我对 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 和 Hashed Timing Wheels解决了这个问题。(2009 年 1 月 19 日)
我正在尝试在 Java 中实现一个特殊用途的计时器,该计时器针对超时处理进行了优化。例如,用户可以注册一个带有截止期限的任务,并且计时器可以在截止期限结束时通知用户的回调方法。在大多数情况下,注册的任务会在很短的时间内完成,因此大多数任务将被取消(例如 task.cancel())或重新安排到未来(例如 task.rescheduleToLater(1, TimeUnit.SECOND)) .
我想使用这个计时器来检测空闲的套接字连接(例如,在 10 秒内没有收到消息时关闭连接)和写入超时(例如,当写入操作在 30 秒内未完成时引发异常。)在大多数情况下,不会发生超时,客户端将发送一条消息并发送响应,除非存在奇怪的网络问题..
我不能使用 java.util.Timer 或 java.util.concurrent.ScheduledThreadPoolExecutor 因为他们认为大多数任务都应该超时。如果一个任务被取消,被取消的任务被存储在它的内部堆中,直到 ScheduledThreadPoolExecutor.purge() 被调用,这是一个非常昂贵的操作。(O(NlogN)也许?)
在我在 CS 课程中学到的传统堆或优先级队列中,在许多情况下更新元素的优先级是一项昂贵的操作 (O(logN),因为它只能通过删除元素并重新插入它来实现新的优先级值。像斐波那契堆这样的堆有 O(1) 时间的 reductionKey() 和 min() 操作,但我至少需要快速 increaseKey() 和 min()(或 reductionKey() 和 max()) .
您是否知道针对此特定用例高度优化的任何数据结构?我正在考虑的一种策略是将所有任务存储在哈希表中并每秒左右迭代所有任务,但这并不是那么漂亮。