問題のクラスを実装する価値があるかどうかを判断するために、純粋にこれを求めています...
同期されていないインスタンスを取得し、リフレクションを使用してそのインスタンスを調査し、同期された呼び出し内に「ラップされた」入力インスタンスを返す Java ユーティリティ クラスを知っていますか?
(つまり: 任意のインスタンスに対して同期化されたデリゲート クラスを作成するファクトリ)
問題のクラスを実装する価値があるかどうかを判断するために、純粋にこれを求めています...
同期されていないインスタンスを取得し、リフレクションを使用してそのインスタンスを調査し、同期された呼び出し内に「ラップされた」入力インスタンスを返す Java ユーティリティ クラスを知っていますか?
(つまり: 任意のインスタンスに対して同期化されたデリゲート クラスを作成するファクトリ)
いいえ、私はそれを行うものを知りません-そして私はめったにそれを使いたくありません.
個々の操作の同期が役立つ機能はほとんどありません。通常、一度にいくつかの操作を同期する必要があります。個々の操作を単純に同期するものは、特定の状況でどの操作をアトミックに実行する必要があるかという実際の決定を処理することなく、スレッドセーフの錯覚を与えます (一部のプログラマーを不注意にするのに十分です)。
Jon Skeetの答えが好きです。木ではなく森を見ています。しかし、質問に答えるには:
インスタンスが何らかのインターフェースに属していると仮定すると、java.lang.reflect.Proxy
これを行うのは簡単です。
public final class SynchronizedFactory {
private SynchronizedFactory() {}
public static <T> T makeSynchronized(Class<T> ifCls, T object) {
return ifCls.cast(Proxy.newProxyInstance(
object.getClass().getClassLoader(),
new Class<?>[] {ifCls},
new Handler<T>(object)));
}
private static class Handler<T> implements InvocationHandler {
private final T object;
Handler(T object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
synchronized (object) {
return method.invoke(object, args);
}
}
}
}
ちなみに、このコードはテストされていません。自己責任。
Chris Jester-Young のソリューションがいかに優れているかに注意を向けたいと思います。私はそれを単純な静的関数にリファクタリングし、以下に含めてうまく使用しています。ありがとうクリス!
/**
* Utility that can take any object that implements a given interface and returns
* a proxy that implements the same interface and synchronizes all calls that are
* delegated to the given object. From Chris Jester-Young, http://about.me/cky
* @param interfaceClass The interface to synchronize. Use MyInterface.class.
* @param object The object to synchronize that implements the given interface class.
* @return A synchronized proxy object that delegates to the given object.
*/
public static <T> T makeSynchronized(Class<T> interfaceClass, final T object) {
return interfaceClass.cast(
Proxy.newProxyInstance(
object.getClass().getClassLoader(),
new Class<?>[]{interfaceClass},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
synchronized (object) {
return method.invoke(object, args);
}
}
}
)
);
}
リフレクションによるオーバーヘッドは、コードをスレッド化することで得られるスピードアップも低下させます...