26

スレッドセーフな共通コードのクラスがあります。

そのクラスのメソッドの 1 つは抽象的であり、実装ごとにオーバーライドする必要があります。

このメソッドのすべての実装がスレッドセーフである必要があることを確認するか、少なくとも他の開発者にフラグを立てる必要があります。

これを行う最善の方法は何ですか?

この効果に対するキーワードまたは注釈はありますか?

既に試しabstract synchronizedましたが、そのキーワードの組み合わせは許可されていません。

4

3 に答える 3

28

直接行うことはできません。できることの 1 つは、メソッドを具象にして、抽象メソッドを呼び出すことです。

public synchronized final void foo() {
    doFoo();
}
protected abstract void doFoo();

そうすれば、doFoo() は常に* foo() によって確立された同期の下で呼び出されます。

* 誰かが直接呼び出さない限り、そうすべきではないことを明確にするために、名前を付けて文書化する必要があります。

于 2012-10-02T05:18:56.697 に答える
1

サブクラスの Synchronized メソッドから

Synchronized は、メソッドの実装の詳細です。同期メソッドを同期として宣言せずにメソッドでオーバーライドすることも、その逆も可能です。オーバーロードについても同じことが言えます。

スーパークラスの同期メソッドは、サブクラスのメソッドと同じロックを取得します

于 2012-10-02T05:25:48.550 に答える
0

このJLSへのリンクは、抽象と同期を混在させることができないことを確認しています。

キーワードや標準の注釈よりもはるかに弱いですが、ドキュメントよりも強力です:おそらくマーカーインターフェイスを試してみてください?

...言語がそのようなメタデータを明示的にサポートしていない場合に、メタデータをクラスに関連付ける手段を提供します。

これは一筋縄ではいきませんが、派生クラスが宣言を行うという点で役立つ可能性があります(編集:新しい例で宣言をテストします)。

interface EatMethodIsThreadSafe {}

abstract class Animal {
    public Animal() {
        if (! (this instanceof EatMethodIsThreadSafe)) { 
            throw new IllegalArgumentException("eat method must be thread safe");
        }
    }
    public abstract void eat();
}

public class Bear extends Animal implements EatMethodIsThreadSafe {
    public synchronized void eat() {}
    public static void main(String...args) { Bear b = new Bear(); } 
}
于 2012-10-02T07:00:06.563 に答える