Advertisement
DulcetAirman

SynchronizedObject

Jan 2nd, 2014
128
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. package ch.claude_martin.enums.proxy;
  2.  
  3. import static java.util.Objects.requireNonNull;
  4.  
  5. import java.lang.reflect.Proxy;
  6. import java.util.Collections;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. import java.util.concurrent.TimeUnit;
  10. import java.util.concurrent.locks.Lock;
  11. import java.util.concurrent.locks.ReentrantLock;
  12.  
  13. /**
  14.  * Allows to make any object thread-safe. This works similar to
  15.  * {@link Collections#synchronizedCollection(java.util.Collection)}. But this
  16.  * uses a proxy, which will synchronize on the object.
  17.  *
  18.  * <p>
  19.  * The object must implement some interface so that the returned proxy can be
  20.  * used as an implementation of that interface.
  21.  *
  22.  * <p>
  23.  * Note: This does not make the elements within the object thread-safe. This
  24.  * only works if the object hides all information and no other objects share
  25.  * references to the inner data structures.
  26.  *
  27.  * @author Claude Martin
  28.  */
  29. public class SynchronizedObject {
  30.  
  31.     /**
  32.      * Returns a proxy instance which will synchronize all calls to the object.
  33.      *
  34.      * @param object
  35.      *          The object which will be used for synchronization and to redirect
  36.      *          all method invocations.
  37.      * @param type
  38.      *          The interface type of the returned proxy. Both the object and the
  39.      *          proxy will share this interface.
  40.      * @return A new tread-safe proxy.
  41.      */
  42.     @SuppressWarnings("unchecked")
  43.     public static <I, T extends I> I synchronize(final T object, final Class<I> type) {
  44.         return (I) Proxy.newProxyInstance(//
  45.             requireNonNull(object).getClass().getClassLoader(),//
  46.             new Class[] { requireNonNull(type) },//
  47.             (proxy, method, args) -> {
  48.                 synchronized (object) {
  49.                     return method.invoke(object, args);
  50.                 }
  51.             });
  52.     }
  53.  
  54.     /**
  55.      * Returns a proxy instance which will synchronize all calls to the object
  56.      * using a given lock.
  57.      *
  58.      * @param object
  59.      *          The object which will be used for synchronization and to redirect
  60.      *          all method invocations.
  61.      * @param type
  62.      *          The interface type of the returned proxy. Both the object and the
  63.      *          proxy will share this interface.
  64.      * @param lock
  65.      *          A lock object used to obtain a lock.
  66.      * @return A new tread-safe proxy.
  67.      */
  68.     @SuppressWarnings("unchecked")
  69.     public static <I, T extends I> I synchronize(final T object, final Class<I> type, final Lock lock) {
  70.         return (I) Proxy.newProxyInstance(//
  71.             requireNonNull(object).getClass().getClassLoader(),//
  72.             new Class[] { requireNonNull(type) },//
  73.             (proxy, method, args) -> {
  74.                 lock.lock();
  75.                 try {
  76.                     return method.invoke(object, args);
  77.                 } finally {
  78.                     lock.unlock();
  79.                 }
  80.             });
  81.     }
  82. }
  83.  
  84. -----------------------------
  85. -----------------------------
  86. (The rest is just for testing)
  87.  
  88. public final class SynchronizedObjectTest {
  89.     public static void main(final String[] args) throws InterruptedException {
  90.         final ICounter counter = synchronize(new Counter(), ICounter.class);
  91.         final ExecutorService pool = Executors.newCachedThreadPool();
  92.         for (int i = 0; i < 10000; i++)
  93.             pool.execute(() -> counter.increment());
  94.         pool.shutdown();
  95.         pool.awaitTermination(1, TimeUnit.MINUTES);
  96.         System.out.println(counter.get());
  97.     }
  98.  
  99.     static interface ICounter {
  100.         public int get();
  101.  
  102.         public void increment();
  103.     }
  104.  
  105.     static class Counter implements ICounter {
  106.         int i = 0;
  107.  
  108.         @Override
  109.         public int get() {
  110.             return this.i;
  111.         }
  112.  
  113.         @Override
  114.         public void increment() {
  115.             this.i++;
  116.         }
  117.     }
  118. }
Advertisement
Advertisement
Advertisement
RAW Paste Data Copied
Advertisement