4

本 Concurrency in Practice (Brian Goetz 著) に記載されているキャッシュの実装を拡張しようとしています。

エントリが 10 秒以内にアクセスされない場合は期限切れになるようにキャッシュを拡張したいと考えています。つまり、キャッシュから削除されます。

このために、以下のように Future と FutureTask を拡張しました

package examples.cache;

import java.util.concurrent.Future;

public interface FutureWithExpire<V> extends Future<V> {
    public boolean isResultExpired();
}

package examples.cache;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class FutureTaskWithExpire<V> extends FutureTask<V> implements FutureWithExpire<V>{
    private final static long validPeriod = 10 * 1000;
    private long expirationTime;

    public FutureTaskWithExpire(Callable<V> callable) {
        super(callable);
    }

    @Override
    public V get() throws InterruptedException,ExecutionException{
        V v = super.get();
        expirationTime = System.currentTimeMillis() + validPeriod;
        return v;
    }

    public boolean isResultExpired(){
    if(isDone()){
        if(expirationTime < System.currentTimeMillis()){
        return true;
        }
    }
    return false;
    }
}

上記のように、有効期限を計算するために get メソッドをオーバーライドしています。

メイン キャッシュ クラス、つまりMemorizerisResultExpiredでは、エントリを定期的にスキャンし、 true を返すエントリを削除する新しいスレッドを開始します。

この実装が機能するかどうか、またはコードにバグがあるかどうかを知りたかっただけですか?

get を Timeout でオーバーライドする必要があることに注意してください。ただし、簡潔にするために、それを省略しました。

4

2 に答える 2

1

そしてもちろんexpirationTimeは揮発性でなければなりません

于 2012-08-15T20:40:11.197 に答える
0

このコードの理由:

 expirationTime = System.currentTimeMillis() + validPeriod;

getメソッドで?コンストラクターにある必要があるように思えます。そうしないと、無効化が速すぎる可能性があります。FutureTaskWithExpireインスタンスとその他のスレッドを作成したとし ます。エントリを無効にするスレッドは isResultExpired メソッドを呼び出します。有効期限は実際にはゼロになるため、まだ有効な時間があったとしても、エントリは無効になります。

また、get と isExpired の呼び出しは、たとえば ReentrantLock で同期する必要があると思います。これは、別のスレッドでそのエントリを指定しようとしているときに、一部のスレッドでエントリを無効にしたくないためです。

于 2012-08-15T07:10:01.973 に答える