1

Brian Goetz の並行性の本から、次のコードの説明を探しています。

public V compute(final A arg) throws InterruptedException {
    while (true) {
        Future<V> f = cache.get(arg);
        if (f == null) {
            Callable<V> eval = new Callable<V>() {
                public V call() throws InterruptedException {
                    return c.compute(arg);
                }
            };
            FutureTask<V> ft = new FutureTask<V>(eval);
            f = cache.putIfAbsent(arg, ft);

            if (f == null) {
                f = ft;
                ft.run();
            }

        }
        try {
            return f.get();
        } catch (CancellationException e) {
            cache.remove(arg, f);
        } catch (ExecutionException e) {
            throw launderThrowable(e.getCause());
        }
    }
}

また、 putIfAbsent() 呼び出しの後、ステートメントがf = ft;直接 ft.​​run() を実行するだけでなく、なぜですか?

4

3 に答える 3

0

コードの考え方は以下の通りです。いくつかの値を計算するリクエストは、異なるスレッドから発信されています。1 つのスレッドが何らかの値の計算を開始した場合、同じ結果を必要とする他のスレッドは計算を複製してはならず、代わりに最初の計算を待機する必要があります。計算が終了すると、結果はキャッシュに保持されます。

このようなパターンの例は、Java クラスのロードです。クラスがロードされていて、別のスレッドも同じクラスのロードを要求している場合、それ自体をロードするのではなく、最初のスレッドの結果を待つ必要があります。同じクラスローダによって..

于 2013-05-10T16:47:24.267 に答える
0

f.get() を返し、キャッシュから f を削除する可能性があるためです。これにより、1 つのコードがすべてのインスタンスで機能します。

    try {
        return f.get();
    } catch (CancellationException e) {
        cache.remove(arg, f);

上記で f を ft への参照に置き換えなかった場合、putIfAbsent が null を返すたびに NPE が発生します。

于 2013-05-10T14:49:49.483 に答える