4

我的问题

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

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

从 index[4,5] 请求消息应该返回: "my","car"

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

4. "my"
5. "car"

我的解决方案?

我正在考虑使用concurrentskiplistsetorconcurrentskiplist地图。我也在考虑从newSingleThreadScheduledExecutor. 我想知道您将如何实现(有效/线程安全)这个或者使用库?

4

2 回答 2

2

我不确定这是否是你想要的,但看起来你需要NavigableMap<K,V>我。

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"
    }
}

现在,不幸的是,没有简单的方法来获得 a 的synchronized版本NavigableMap<K,V>,但 aSortedMap确实有 a subMap,但只有一个重载,其上限是严格排他的。

API 链接

于 2010-05-13T05:04:46.297 回答
2

据我所知,最大的担忧是如何让某些元素在一段时间后过期。我有类似的要求,我创建了一个实现延迟接口的消息类。这个类包含了我需要的所有信息,并且(通过延迟接口)告诉我它什么时候过期。

我在并发集合中使用了该对象的实例,您可以使用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;
    }
}
于 2010-05-14T00:56:55.933 回答