4

私の問題

ロングポーリングアプリケーションのために、ある種のデータ構造でメッセージを保持したいとします。

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

index [4,5]からのメッセージを要求すると、次のように返されます "my","car"

次に、しばらくすると、古いメッセージは役に立たなくなったため、メモリを節約したいので、それらを削除したいとします。x時間の経過後にメッセージ[1-3]が古くなったとしましょう。x1秒に1回だけ削除するのが最も効率的だと思います。次に、私のデータ構造には次のものが含まれている必要があります。

4. "my"
5. "car"

私の解決策は?

concurrentskiplistsetまたはconcurrentskiplistマップを使用することを考えていました。また、の中から古いメッセージを削除することを考えていました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"
    }
}

残念ながらsynchronized、のバージョンを取得する簡単な方法はありませんが、NavigableMap<K,V>aにはがありますが、上限が厳密に排他的であるオーバーロードは1つだけです。SortedMapsubMap

APIリンク

于 2010-05-13T05:04:46.297 に答える
2

私が収集する大きな懸念は、特定の要素を一定期間後に期限切れにする方法です。同様の要件があり、 DelayedInterfaceを実装するメッセージクラスを作成しました。このクラスは、メッセージに必要なすべてのものを保持し、(遅延インターフェイスを介して)メッセージの有効期限が切れたときに通知しました。

並行コレクション内でこのオブジェクトのインスタンスを使用しました。整数キーでこれらのオブジェクトにキーを設定できるため、 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 に答える