【问题标题】:queue with time stamped elements within a time period一个时间段内带有时间戳元素的队列
【发布时间】:2011-10-02 10:45:17
【问题描述】:

我想存储在队列中,数据结构无关紧要,只有我在当前时间最后 5 分钟内插入的元素。任何较旧的东西都应该被删除——这样每当我得到队列的大小时,它就会给出最后 5 分钟插入的对象的计数。

基本上我只需要知道我的应用在进行下一次调用之前的最后 5 分钟内对服务器进行了多少次 http 调用。

如果有人知道一些现有的库可能有这个实现,请分享。

【问题讨论】:

  • 您忘记提及以下内容:所需的平台/语言/等等...

标签: java data-structures queue


【解决方案1】:

您可以使用带有时间戳的优先队列作为键。因此,当您调用 Peek() 时,您始终会获得仍在队列中的最旧时间戳。然后每次查询窗口大小内的项目数时:清理窗口外的项目并返回仍在优先级队列中的项目数。

例如:

public class CountInWindow {

    /**
     * Adding a main just for testing 
     * @param args
     * @throws InterruptedException 
     */
    public static void main(String[] args) throws InterruptedException {
        System.out.println("test started");
        CountInWindow test = new CountInWindow(5000); //5 seconds for testing
        test.debug = true;
        test.insertTimeStamp(System.currentTimeMillis());
        Thread.sleep(100);//sleep 
        test.insertTimeStamp(System.currentTimeMillis());
        Thread.sleep(100);//sleep 
        test.insertTimeStamp(System.currentTimeMillis());
        Thread.sleep(100);//sleep 
        test.insertTimeStamp(System.currentTimeMillis());
        Thread.sleep(5040);//sleep 5 secs
        test.insertTimeStamp(System.currentTimeMillis());
        Thread.sleep(100);//sleep 
        test.insertTimeStamp(System.currentTimeMillis());
        System.out.println(test.getWindowCount()); //Should be 2 not 6.
        System.out.println("test done");
    }

    java.util.PriorityQueue<Long> window;
    public static final long FIVE_MINS_IN_MS = 300000l;
    public final long WINDOW_SIZE;
    public boolean debug = false;

    //Constructor which defaults to 5mins
    public CountInWindow(){
        WINDOW_SIZE = FIVE_MINS_IN_MS;
        window = new java.util.PriorityQueue<Long>();
    }
    //Constructor for any size window
    public CountInWindow(long windowSize){
        WINDOW_SIZE = windowSize;
        window = new java.util.PriorityQueue<Long>();
    }
    /**
     * Add a new timestamp to the window's queue
     * @param ts
     */
    public void insertTimeStamp(long ts){
        window.add(ts);
    }
    /**
     * Clean up items outside the window size and then return the count of times still in the window.
     * @return A count of timestamps still inside the 5 mins window.
     */
    public int getWindowCount(){
        long currTime = System.currentTimeMillis();
        //Clean out old Timestamps
        while((currTime - window.peek().longValue()) > WINDOW_SIZE){
            long drop = window.remove().longValue();
            if(debug)System.out.println("dropping item:" + drop);
        }
        return window.size();
    }
}

【讨论】:

  • 在场景中是否真的需要优先级队列,因为项目是按时间戳插入的,并且会按顺序排列。 queue.peek() 仅仅一个队列接口就足够了吗?
【解决方案2】:

用什么语言?队列是持久的还是内存中的?

如果您在 Java 中需要这种行为,您可以使用 DelayedQueue,并有一个单独的线程在紧密循环中连续调用 queue.take() 以排出过期项目。然后,queue.size() 将为您提供队列中剩余未过期项目的大小。这就要求你放入DelayedQueue的项目实现Delayed接口,并将5分钟的值返回给.getDelay()方法。

【讨论】:

  • 谢谢,但这种方法的唯一问题是线程必须非常频繁地运行才能使结果最适合调用 queue.size()
  • 是的——它必须是一个紧密的循环(例如,while queue.take() != null)。请注意, queue.take() 将阻塞,直到队列有过期的元素被占用。然后,迭代的频率取决于项目在队列中放置的频率(以及它们过期的频率),而不是基于时间的垃圾收集(因此 queue.size() 将完全准确次)。
  • 谢谢,我没有意识到 queue.take() 会阻塞,直到队列中的元素过期。了解他们如何实现 DelayQueue 会很有趣——可能他们在内部使用 2 个队列,一个用于保存过期元素,一个用于保存未过期元素。无论如何,非常感谢 - 你们非常乐于助人 - 我想给你一张 25 美元的签证礼品卡作为 tankyou 代币 - 不知道如何发送
  • 哈哈——没必要!我试着回馈一点,以换取我在这里学到的所有东西。
【解决方案3】:

我已经实现了一个FadingLinkedList 喜欢

public class FadingLinkedList<E> {

private transient Entry<E> header = new Entry<E>(null, null);

/**
 * ms
 */
private long livingTime;

/**
 * Constructs FadingLinkedList with elements of living time livingTime in
 * milliseconds
 */
public FadingLinkedList(long livingTime) {
    this.livingTime = livingTime;
}

/**
 * remove all faded elements,
 *
 * @return the count of not faded
 */
public synchronized int removeFaded() {
    long now = System.nanoTime();
    int count = 0;
    Entry<E> prev = header;// the last living Entry in the loop
    for (Entry<E> e = header.next; e != null; e = e.next) {
        if (TimeUnit.NANOSECONDS.toMillis(now - e.birthTime) >= livingTime) {
            // cut off this list here.
            prev.next = null;
            break;
        }
        count++;
        prev = e;
    }
    return count;
}

/**
 * Returns the number of elements that not faded.
 */
public int size() {
    return removeFaded();
}

public synchronized void push(E e) {
    Entry<E> newEntry = new Entry<E>(e, header.next);
    header.next = newEntry;
}

private static class Entry<E> {
    E element;
    Entry<E> next;
    long birthTime;

    Entry(E element, Entry<E> next) {
        this.element = element;
        this.next = next;
        this.birthTime = System.nanoTime();
    }
}

public synchronized void clear() {
    header.next = null;
}

public synchronized int getAndClear() {
    int size = size();
    clear();
    return size;
}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-08
    • 2019-08-22
    • 2022-06-14
    • 1970-01-01
    • 2021-02-08
    • 2019-11-20
    • 1970-01-01
    • 2022-11-28
    相关资源
    最近更新 更多