スレッドセーフな共通コードのクラスがあります。
そのクラスのメソッドの 1 つは抽象的であり、実装ごとにオーバーライドする必要があります。
このメソッドのすべての実装がスレッドセーフである必要があることを確認するか、少なくとも他の開発者にフラグを立てる必要があります。
これを行う最善の方法は何ですか?
この効果に対するキーワードまたは注釈はありますか?
既に試しabstract synchronized
ましたが、そのキーワードの組み合わせは許可されていません。
スレッドセーフな共通コードのクラスがあります。
そのクラスのメソッドの 1 つは抽象的であり、実装ごとにオーバーライドする必要があります。
このメソッドのすべての実装がスレッドセーフである必要があることを確認するか、少なくとも他の開発者にフラグを立てる必要があります。
これを行う最善の方法は何ですか?
この効果に対するキーワードまたは注釈はありますか?
既に試しabstract synchronized
ましたが、そのキーワードの組み合わせは許可されていません。
直接行うことはできません。できることの 1 つは、メソッドを具象にして、抽象メソッドを呼び出すことです。
public synchronized final void foo() {
doFoo();
}
protected abstract void doFoo();
そうすれば、doFoo() は常に* foo() によって確立された同期の下で呼び出されます。
* 誰かが直接呼び出さない限り、そうすべきではないことを明確にするために、名前を付けて文書化する必要があります。
Synchronized は、メソッドの実装の詳細です。同期メソッドを同期として宣言せずにメソッドでオーバーライドすることも、その逆も可能です。オーバーロードについても同じことが言えます。
この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(); }
}