包含过期条目的 Java 集合

发布于 2025-01-08 22:10:30 字数 654 浏览 2 评论 0原文

我需要跟踪指定时间范围内的某些事件,并在事件数量达到一定数量时采取行动。更详细地说,我连接到外部服务并提交请求,这些请求的状态已确认为 CONF 或 FAIL。我需要能够监视响应,以检测在给定时间范围内是否出现异常数量的失败,例如,在最后 5 秒内失败超过 3 次,以便我可以检查错误并采取相应措施。我也可以检查连续 3 次失败,但我更喜欢基于时间的方法。

在阅读这篇帖子后,我一直在测试Guava的CacheLoader,但是当条目(我只存储FAIL-缓存中的事件)似乎按预期过期,对 size() 的调用(以确定失败次数)也包括过期的条目。根据 文档,如果我没有误解的话?有没有办法从缓存中获取“活动”事件的数量?

我想另一种解决方案是使用像 Esper 这样的 CEP 框架,但对于我的简单需求来说,这似乎有点矫枉过正和麻烦。有没有人有完全不同的方法来建议可以满足我的要求?谢谢

I need to track certain events over a specified time frame and act if the number of events reaches a certain number. In more detail, I connect to an external service and submit requests which are acknowledged with a status that equals CONF or FAIL. I need to be able to monitor the responses to detect if I get an unusual number of fails in a given time frame, e.g. >3 fails during the last 5 seconds, so that I can check for errors and act accordingly. I could alternatively check for 3 fails in a row but I prefer a time based approach.

I have been testing Guava's CacheLoader after reading this post but while entries (I only store FAIL-events) in the Cache appears to expire as expected, a call to size() (to determine number of fails) includes also the expired entries. This appears to be how it is supposed to work according to the documentation, if I have not misunderstood things?? Is there any way to get the number of 'active' events from a Cache?

I guess an alternative solution is to use a CEP-framework like Esper but it seems like overkill and cumbersome for my simple needs. Does anyone have a completely different approach to suggest that would facilitate my requirement? Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

风流物 2025-01-15 22:10:30

Cache获取活动元素的确切数量需要锁定整个缓存,这是非常昂贵的。不过,您也许可以使用 cleanUp() 方法来确保 size 不会意外地计算已被悄悄逐出的条目。

我不会依赖这给你准确的结果,但它应该显着提高结果的准确性。

Getting the exact number of active elements from the Cache would require locking the entire cache, which is extremely expensive. You might be able to use the cleanUp() method to make sure that size is not accidentally counting entries that have been quietly evicted, though.

I would not depend on this giving you exact results, but it should improve the accuracy of the results significantly.

孤独岁月 2025-01-15 22:10:30

我认为 Guava 集合与您想要的功能最接近的是 MinMaxPriorityQueue 具有有限的最大大小。您必须按时间顺序排列失败事件,并定期检查第一个和最后一个元素之间的差异以及它是否已满。

但你本质上想要的是一米。您可以尝试使用 Coda Hale 指标库中的此 Meter

I think Guava collection with the nearest functionality to what you want is MinMaxPriorityQueue with a limited maximum size. You'd have to put failure events in chronological order and check periodically for the difference between first and last element and whether it is full.

But what you essentially want is a meter. You can try this Meter from Coda Hale's Metrics library.

奈何桥上唱咆哮 2025-01-15 22:10:30

您可以装饰一个集合实现来做到这一点。像这样的事情:

public class ExpirableArrayList<E> extends ArrayList<E> {

    private final Date creation = new Date();

    private final long timeToLiveInMs;

    public ExpirableArrayList(long timeToLiveInMs, int initialCapacity) {
        super(initialCapacity);
        this.timeToLiveInMs = timeToLiveInMs;
    }

    public ExpirableArrayList(long timeToLiveInMs) {
        this.timeToLiveInMs = timeToLiveInMs;
    }

    public ExpirableArrayList(long timeToLiveInMs, Collection<? extends E> c) {
        super(c);
        this.timeToLiveInMs = timeToLiveInMs;
    }

    private void expire() {
        if (System.currentTimeMillis() - creation.getTime() > timeToLiveInMs) {
            clear();
        }
    }

    @Override
    public int size() {
        expire();
        return super.size();
    }

    @Override
    public boolean isEmpty() {
        expire();
        return super.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        expire();
        return super.contains(o);
    }

    @Override
    public Iterator<E> iterator() {
        expire();
        return super.iterator();
    }

    @Override
    public Object[] toArray() {
        expire();
        return super.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        expire();
        return super.toArray(a);
    }

    @Override
    public boolean add(E e) {
        expire();
        return super.add(e);
    }

    @Override
    public boolean remove(Object o) {
        expire();
        return super.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        expire();
        return super.contains(c);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        expire();
        return super.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        expire();
        return super.addAll(index, c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        expire();
        return super.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        expire();
        return super.retainAll(c);
    }

    @Override
    public E get(int index) {
        expire();
        return super.get(index);
    }

    @Override
    public E set(int index, E element) {
        expire();
        return super.set(index, element);
    }

    @Override
    public E remove(int index) {
        expire();
        return super.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        expire();
        return indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        expire();
        return lastIndexOf(o);
    }

    @Override
    public ListIterator<E> listIterator() {
        expire();
        return listIterator();
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        expire();
        return listIterator();
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        expire();
        return subList(fromIndex, toIndex);
    }
}

You could decorate a collection implementation to do that. Something like this:

public class ExpirableArrayList<E> extends ArrayList<E> {

    private final Date creation = new Date();

    private final long timeToLiveInMs;

    public ExpirableArrayList(long timeToLiveInMs, int initialCapacity) {
        super(initialCapacity);
        this.timeToLiveInMs = timeToLiveInMs;
    }

    public ExpirableArrayList(long timeToLiveInMs) {
        this.timeToLiveInMs = timeToLiveInMs;
    }

    public ExpirableArrayList(long timeToLiveInMs, Collection<? extends E> c) {
        super(c);
        this.timeToLiveInMs = timeToLiveInMs;
    }

    private void expire() {
        if (System.currentTimeMillis() - creation.getTime() > timeToLiveInMs) {
            clear();
        }
    }

    @Override
    public int size() {
        expire();
        return super.size();
    }

    @Override
    public boolean isEmpty() {
        expire();
        return super.isEmpty();
    }

    @Override
    public boolean contains(Object o) {
        expire();
        return super.contains(o);
    }

    @Override
    public Iterator<E> iterator() {
        expire();
        return super.iterator();
    }

    @Override
    public Object[] toArray() {
        expire();
        return super.toArray();
    }

    @Override
    public <T> T[] toArray(T[] a) {
        expire();
        return super.toArray(a);
    }

    @Override
    public boolean add(E e) {
        expire();
        return super.add(e);
    }

    @Override
    public boolean remove(Object o) {
        expire();
        return super.remove(o);
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        expire();
        return super.contains(c);
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        expire();
        return super.addAll(c);
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        expire();
        return super.addAll(index, c);
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        expire();
        return super.removeAll(c);
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        expire();
        return super.retainAll(c);
    }

    @Override
    public E get(int index) {
        expire();
        return super.get(index);
    }

    @Override
    public E set(int index, E element) {
        expire();
        return super.set(index, element);
    }

    @Override
    public E remove(int index) {
        expire();
        return super.remove(index);
    }

    @Override
    public int indexOf(Object o) {
        expire();
        return indexOf(o);
    }

    @Override
    public int lastIndexOf(Object o) {
        expire();
        return lastIndexOf(o);
    }

    @Override
    public ListIterator<E> listIterator() {
        expire();
        return listIterator();
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        expire();
        return listIterator();
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        expire();
        return subList(fromIndex, toIndex);
    }
}
他夏了夏天 2025-01-15 22:10:30

我没有使用过它,但它看起来像 可能会满足您的需求

I haven't used it but it looks like this might satisfy your needs

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文