DelayQueue具有更高的速度remove()?

时间:2012-11-16 16:51:02

标签: java performance

我有一个项目跟踪超过500k对象的状态信息,程序接收关于这些对象的10k更新/秒,更新包括新的,更新或删除操作。

作为程序的一部分,必须大约每五分钟对这些对象执行一次内部管理,为此,我将它们放在实现DelayQueue接口的Delayed中,允许阻塞功能DelayQueue来控制这些物品的保管。

  • 新的时候,对象会放在DelayQueue

  • 更新后,对象为remove()来自DelayQueue,已更新,然后重新插入其更新信息所指示的新位置。

  • 删除后,remove()中的对象为DelayQueue

我面临的问题是,一旦队列传递了大约450k个对象,remove()方法就会变得非常长。

该程序是多线程的,一个线程处理更新,另一个线程处理内容。由于remove()延迟,我们遇到了令人讨厌的锁定性能问题,并且最终更新线程缓冲区消耗了所有堆空间。

我设法通过创建DelayedWeakReference (extends WeakReference implements Delayed)来解决这个问题,它允许我将“影子”对象留在队列中,直到它们正常到期为止。

这会消除性能问题,但会导致内存需求大幅增加。这样做会导致实际需要在队列中的每个对象大约5 DelayedWeakReference

是否有人知道DelayQueue有额外的跟踪功能,可以进行快速remove()操作?或者有什么建议可以更好地处理这个问题,而不会消耗更多的内存?

3 个答案:

答案 0 :(得分:2)

我花了一些时间考虑这个,
但在阅读了你有趣的问题几分钟之后,这是我的想法:
A.如果你的对象有某种ID,用它来散列,实际上没有一个延迟队列,但有N个延迟队列。
这将使锁定系数降低N.
将有一个中央数据结构,
持有这N个队列。由于N是预先配置的,因此 您可以在系统启动时创建所有N个队列。

答案 1 :(得分:1)

如果你只需要“大约每五分钟”进行一次家务管理,这就是维持这种情况所需的工作。

我要做的是有一个任务,每分钟运行一次(或根据需要减少),以查看自上次更新以来是否已经过了五分钟。如果使用此方法,则无需维护其他集合,并且更新时不会更改任何数据结构。扫描组件的开销增加,但是不变。执行更新的开销变得微不足道(设置上次更新的字段)

答案 2 :(得分:0)

如果我理解你的问题,你想对某个对象做一些事情,如果它没有被触摸过5分钟。

您可以拥有自定义链接列表;尾巴是最近感动的。删除节点很快。

簿记线程可以每1秒唤醒一次,并移除5分钟的头部。但是,如果1秒延迟是不可接受的,则计算确切的暂停时间

// book keeping thread

void run()

  synchronized(list) 

    while(true)

        if(head==null)
            wait();
        else if(  head.time + 5_min > now )
            wait( head.time + 5_min - now );
        else 
            remove head
            process it


// update thread

void add(node)
  synchronized(list) 
    append node
    if size==1
        notify()  

void remove(node)
  synchronized(list) 
    remove node