带时间引用的标准Java队列数据结构?

时间:2014-06-02 09:18:22

标签: java algorithm data-structures queue

为了实现每个时间数量的请求数量限制的服务,我寻找在enqueue()/add()命令超过某个频率时拒绝添加元素的队列的实现?

因此,例如,您可以每秒不再调用enqueue()/add() 1000次,并防止高资源消耗服务DDOS。

如果超出队列容量,队列必须拒绝enqueue()/add()(直到您致电dequeue()/remove())。

2 个答案:

答案 0 :(得分:1)

你想拒绝一个例外,或者你只是想忽略它们。

更好的方法可能是更新Map并忽略给定键的重复更新。这会丢弃您无法处理的事件,但始终确保最新更新密钥。

这样,您每秒消耗N条新消息,并且可以正常删除重复项。

e.g。

final ConcurrentMap<String, Message> map = new ConcurrentHashMap<>();
final BlockingQueue<String> queue = new ArrayBlockingQueue<>(10000);
int updateCount = 0;
long lastUpdate = 0;

public void enqueue(String key, Message message) {
    map.put(key, message);
    queue.offer(key);
}

public Message dequeue() throws InterruptedException {
    long updateTime = System.currentTimeMillis();
    long time = updateTime - lastUpdate;
    lastUpdate = updateTime;
    if (time > count)
        count = 0;
    else
        count -= time;
    if (count > 1000)
        Thread.sleep(1);
    count++;
    while(true) {
       String key = queue.take();
       Message msg = map.remove(key);
       if (msg != null)
           return msg;
       // if the msg is null, we have already sent the latest update for that key
    }
 }

这将为您提供每秒1000的更新速率,并始终为您提供任何密钥的最新更新。

答案 1 :(得分:1)

实现此目的的一种简单方法是在请求新的排队/添加操作时检查以下内容:

  
      
  1. 检查队列是否已满
  2.   
  3. 检查自上次排队操作以来的时间是否> 1/1000秒。   2a)你可以通过保持时间来修改上面的第2点   1000枚最新排队行动的印章。每当请求入队操作时,请检查自此队列中进行的第一次操作以来的时间。   如果超过1秒,则从时间戳队列中弹出该操作并添加它   之一。
  4.