Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package ch.claude_martin.enums.proxy;
- import static java.util.Objects.requireNonNull;
- import java.lang.reflect.Proxy;
- import java.util.Collections;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.TimeUnit;
- import java.util.concurrent.locks.Lock;
- import java.util.concurrent.locks.ReentrantLock;
- /**
- * Allows to make any object thread-safe. This works similar to
- * {@link Collections#synchronizedCollection(java.util.Collection)}. But this
- * uses a proxy, which will synchronize on the object.
- *
- * <p>
- * The object must implement some interface so that the returned proxy can be
- * used as an implementation of that interface.
- *
- * <p>
- * Note: This does not make the elements within the object thread-safe. This
- * only works if the object hides all information and no other objects share
- * references to the inner data structures.
- *
- * @author Claude Martin
- */
- public class SynchronizedObject {
- /**
- * Returns a proxy instance which will synchronize all calls to the object.
- *
- * @param object
- * The object which will be used for synchronization and to redirect
- * all method invocations.
- * @param type
- * The interface type of the returned proxy. Both the object and the
- * proxy will share this interface.
- * @return A new tread-safe proxy.
- */
- @SuppressWarnings("unchecked")
- public static <I, T extends I> I synchronize(final T object, final Class<I> type) {
- return (I) Proxy.newProxyInstance(//
- requireNonNull(object).getClass().getClassLoader(),//
- new Class[] { requireNonNull(type) },//
- (proxy, method, args) -> {
- synchronized (object) {
- return method.invoke(object, args);
- }
- });
- }
- /**
- * Returns a proxy instance which will synchronize all calls to the object
- * using a given lock.
- *
- * @param object
- * The object which will be used for synchronization and to redirect
- * all method invocations.
- * @param type
- * The interface type of the returned proxy. Both the object and the
- * proxy will share this interface.
- * @param lock
- * A lock object used to obtain a lock.
- * @return A new tread-safe proxy.
- */
- @SuppressWarnings("unchecked")
- public static <I, T extends I> I synchronize(final T object, final Class<I> type, final Lock lock) {
- return (I) Proxy.newProxyInstance(//
- requireNonNull(object).getClass().getClassLoader(),//
- new Class[] { requireNonNull(type) },//
- (proxy, method, args) -> {
- lock.lock();
- try {
- return method.invoke(object, args);
- } finally {
- lock.unlock();
- }
- });
- }
- }
- -----------------------------
- -----------------------------
- (The rest is just for testing)
- public final class SynchronizedObjectTest {
- public static void main(final String[] args) throws InterruptedException {
- final ICounter counter = synchronize(new Counter(), ICounter.class);
- final ExecutorService pool = Executors.newCachedThreadPool();
- for (int i = 0; i < 10000; i++)
- pool.execute(() -> counter.increment());
- pool.shutdown();
- pool.awaitTermination(1, TimeUnit.MINUTES);
- System.out.println(counter.get());
- }
- static interface ICounter {
- public int get();
- public void increment();
- }
- static class Counter implements ICounter {
- int i = 0;
- @Override
- public int get() {
- return this.i;
- }
- @Override
- public void increment() {
- this.i++;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement