Java: утилита синхронизации - PullRequest
3 голосов
/ 13 апреля 2009

Я прошу это чисто, чтобы определить целесообразность реализации класса в вопросе ...

Знаете ли вы о служебном классе Java, который принимает несинхронизированный экземпляр, использует отражение для исследования этого экземпляра и возвращает входной экземпляр, «обернутый» в синхронизированные вызовы?

(то есть: фабрика, которая создает синхронизированный класс делегата для любого экземпляра)

Ответы [ 4 ]

8 голосов
/ 13 апреля 2009

Нет, я не знаю ничего, что делает это - и я бы редко хотел использовать это.

Синхронизация отдельных операций - редко полезная функция. Обычно вы хотите синхронизировать несколько операций одновременно. То, что просто синхронизирует отдельные операции, дает иллюзию поточной безопасности (достаточно, чтобы сделать некоторых программистов небрежными), не имея дело с реальными решениями о том, какие операции нужно выполнять атомарным образом для любой конкретной ситуации.

7 голосов
/ 13 апреля 2009

Мне нравится ответ Джона Скита; это видит лес вместо деревьев. Но чтобы ответить на вопрос:

Предполагая, что экземпляр принадлежит какому-либо интерфейсу, для этого просто использовать 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);
            }
        }
    }
}

Этот код, кстати, не тестировался. Используйте на свой страх и риск.

1 голос
/ 21 января 2014

Хочу обратить внимание на то, насколько классным является решение Криса Джестера-Янга. Я преобразовал его в простую статическую функцию, которую я успешно использовал, и включил ее ниже. Спасибо Крис!

/**
 * 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);
                    }
                }
            }
        )
    );
}
0 голосов
/ 28 апреля 2009

Затраты на рефлексию также снизили бы скорость, которую вы получите, поточив свой код ...

...