查找从某个键到某个键的消息,同时能够删除过时的键

发布于 2024-09-01 16:59:15 字数 536 浏览 1 评论 0原文

我的问题

假设我想将消息保存在某种用于长轮询应用程序的数据结构中:

1. "dude"
2. "where"
3. "is"
4. "my"
5. "car"

从索引 [4,5] 请求消息应该返回: “我的”,“汽车”

接下来,我们假设一段时间后我想清除旧消息,因为它们不再有用并且我想节省内存。假设一段时间后,x 条消息[1-3] 就变得过时了。我认为每 x 秒删除一次是最有效的。接下来我的数据结构应该包含:

4. "my"
5. "car"

我的解决方案?

我正在考虑使用 concurrentskiplistsetconcurrentskiplist 映射。另外,我正在考虑从 newSingleThreadScheduledExecutor 内部删除旧消息。我想知道你将如何实现(高效/线程安全)这个或者可能使用库?

My problem

Let's say I want to hold my messages in some sort of datastructure for longpolling application:

1. "dude"
2. "where"
3. "is"
4. "my"
5. "car"

Asking for messages from index[4,5] should return:
"my","car".

Next let's assume that after a while I would like to purge old messages because they aren't useful anymore and I want to save memory. Let's say after time x messages[1-3] became stale. I assume that it would be most efficient to just do the deletion once every x seconds. Next my datastructure should contain:

4. "my"
5. "car"

My solution?

I was thinking of using a concurrentskiplistset or concurrentskiplist map. Also I was thinking of deleting the old messages from inside a newSingleThreadScheduledExecutor. I would like to know how you would implement(efficiently/thread-safe) this or maybe use a library?

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

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

发布评论

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

评论(2

你怎么这么可爱啊 2024-09-08 16:59:15

据我了解,最大的问题是如何让某些元素在一段时间后过期。我有类似的要求,我创建了一个实现 延迟界面。这个类保存了消息所需的一切,并(通过延迟接口)告诉我消息何时过期。

我在并发集合中使用了该对象的实例,您可以使用 ConcurrentMap 因为它允许您使用整数键为这些对象设置键。

我每隔一段时间就收割一次收藏,删除那些延迟已过的物品。我们使用 Delayed 接口的 getDelay 方法来测试过期情况:

message.getDelay(TimeUnit.MILLISECONDS);

我使用了一个普通线程,它会休眠一段时间,然后获取过期的项目。根据我的要求,一旦延迟期满就将这些项目删除并不重要。看来你也有类似的灵活性。

如果您需要在延迟到期后立即删除项目,那么您不会在收割线程中休眠一段设定的时间,而是在首先到期的消息的延迟期间休眠。

这是我的延迟消息类:

class DelayedMessage implements Delayed {

    long endOfDelay;
    Date requestTime;
    String message;

    public DelayedMessage(String m, int delay) {
        requestTime = new Date();
        endOfDelay = System.currentTimeMillis()
                + delay;
        this.message = m;
    }

    public long getDelay(TimeUnit unit) {
        long delay = unit.convert(
                endOfDelay - System.currentTimeMillis(),
                TimeUnit.MILLISECONDS);
        return delay;
    }

    public int compareTo(Delayed o) {
        DelayedMessage that = (DelayedMessage) o;
        if (this.endOfDelay < that.endOfDelay) {
            return -1;

        }
        if (this.endOfDelay > that.endOfDelay) {
            return 1;
        }
        return this.requestTime.compareTo(that.requestTime);
    }

    @Override
    public String toString() {
        return message;
    }
}

The big concern, as I gather it, is how to let certain elements expire after a period. I had a similar requirement and I created a message class that implemented the Delayed Interface. This class held everything I needed for a message and (through the Delayed interface) told me when it has expired.

I used instances of this object within a concurrent collection, you could use a ConcurrentMap because it will allow you to key those objects with an integer key.

I reaped the collection once every so often, removing items whose delay has passed. We test for expiration by using the getDelay method of the Delayed interface:

message.getDelay(TimeUnit.MILLISECONDS);

I used a normal thread that would sleep for a period then reap the expired items. In my requirements it wasn't important that the items be removed as soon as their delay had expired. It seems that you have a similar flexibility.

If you needed to remove items as soon as their delay expired, then instead of sleeping a set period in your reaping thread, you would sleep for the delay of the message that will expire first.

Here's my delayed message class:

class DelayedMessage implements Delayed {

    long endOfDelay;
    Date requestTime;
    String message;

    public DelayedMessage(String m, int delay) {
        requestTime = new Date();
        endOfDelay = System.currentTimeMillis()
                + delay;
        this.message = m;
    }

    public long getDelay(TimeUnit unit) {
        long delay = unit.convert(
                endOfDelay - System.currentTimeMillis(),
                TimeUnit.MILLISECONDS);
        return delay;
    }

    public int compareTo(Delayed o) {
        DelayedMessage that = (DelayedMessage) o;
        if (this.endOfDelay < that.endOfDelay) {
            return -1;

        }
        if (this.endOfDelay > that.endOfDelay) {
            return 1;
        }
        return this.requestTime.compareTo(that.requestTime);
    }

    @Override
    public String toString() {
        return message;
    }
}
胡大本事 2024-09-08 16:59:15

我不确定这是否是您想要的,但看起来您需要一个 NavigableMap 给我。

import java.util.*;
public class NaviMap {
    public static void main(String[] args) {
        NavigableMap<Integer,String> nmap = new TreeMap<Integer,String>();
        nmap.put(1, "dude");
        nmap.put(2, "where");
        nmap.put(3, "is");
        nmap.put(4, "my");
        nmap.put(5, "car");

        System.out.println(nmap);
        // prints "{1=dude, 2=where, 3=is, 4=my, 5=car}"        

        System.out.println(nmap.subMap(4, true,  5, true).values());
        // prints "[my, car]"              ^inclusive^  

        nmap.subMap(1, true, 3, true).clear();
        System.out.println(nmap);
        // prints "{4=my, 5=car}"

        // wrap into synchronized SortedMap
        SortedMap<Integer,String> ssmap =Collections.synchronizedSortedMap(nmap);

        System.out.println(ssmap.subMap(4, 5));
        // prints "{4=my}"                 ^exclusive upper bound!

        System.out.println(ssmap.subMap(4, 5+1));
        // prints "{4=my, 5=car}"          ^ugly but "works"
    }
}

现在,不幸没有简单的方法来获取 NavigableMap同步版本,而是获取 SortedMap code> 确实有一个 subMap,但只有一个重载,其中上限是严格排他的。

API 链接

I'm not sure if this is what you want, but it looks like you need a NavigableMap<K,V> to me.

import java.util.*;
public class NaviMap {
    public static void main(String[] args) {
        NavigableMap<Integer,String> nmap = new TreeMap<Integer,String>();
        nmap.put(1, "dude");
        nmap.put(2, "where");
        nmap.put(3, "is");
        nmap.put(4, "my");
        nmap.put(5, "car");

        System.out.println(nmap);
        // prints "{1=dude, 2=where, 3=is, 4=my, 5=car}"        

        System.out.println(nmap.subMap(4, true,  5, true).values());
        // prints "[my, car]"              ^inclusive^  

        nmap.subMap(1, true, 3, true).clear();
        System.out.println(nmap);
        // prints "{4=my, 5=car}"

        // wrap into synchronized SortedMap
        SortedMap<Integer,String> ssmap =Collections.synchronizedSortedMap(nmap);

        System.out.println(ssmap.subMap(4, 5));
        // prints "{4=my}"                 ^exclusive upper bound!

        System.out.println(ssmap.subMap(4, 5+1));
        // prints "{4=my, 5=car}"          ^ugly but "works"
    }
}

Now, unfortunately there's no easy way to get a synchronized version of a NavigableMap<K,V>, but a SortedMap does have a subMap, but only one overload where the upper bound is strictly exclusive.

API links

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