diff --git a/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java new file mode 100644 index 000000000..f27ffc6a9 --- /dev/null +++ b/lazy-loading/src/test/java/com/iluwatar/lazy/loading/HolderThreadSafeTest.java @@ -0,0 +1,42 @@ +package com.iluwatar.lazy.loading; + +import org.junit.Test; + +import java.lang.reflect.Field; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +/** + * Using reflection this test shows that the heavy field is not instantiated until the method getHeavy is called + * + * Created by jones on 11/10/2015. + */ +public class HolderThreadSafeTest { + + @Test + public void test() throws IllegalAccessException { + HolderThreadSafe hts = new HolderThreadSafe(); + + {//first call is null + Field[] ff = HolderThreadSafe.class.getDeclaredFields(); + for (Field f: ff) { + f.setAccessible(true); + } + + assertNull(ff[0].get(hts)); + } + + // now it is lazily loaded + hts.getHeavy(); + + {//now it is not null - call via reflection so that the test is the same before and after + Field[] ff = HolderThreadSafe.class.getDeclaredFields(); + for (Field f: ff) { + f.setAccessible(true); + } + + assertNotNull(ff[0].get(hts)); + } + } +} diff --git a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java index f9b62e798..c50c99e65 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java +++ b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeLazyLoadedIvoryTower.java @@ -4,6 +4,8 @@ package com.iluwatar.singleton; * Thread-safe Singleton class. * The instance is lazily initialized and thus needs synchronization * mechanism. + * + * Note: if created by reflection then a singleton will not be created but multiple options in the same classloader */ public class ThreadSafeLazyLoadedIvoryTower { diff --git a/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java b/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java index ca88f4169..07f99005e 100644 --- a/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java +++ b/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java @@ -2,73 +2,78 @@ package com.iluwatar.singleton; import org.junit.Test; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.*; + +import static org.junit.Assert.assertEquals; + /** - * - * This test case demonstrates thread safety issues of lazy loaded Singleton implementation. - *
- * Out of the box you should see the test output something like the following: - *
- * Thread=Thread-4 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@6fde356e - * Thread=Thread-2 creating instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@6fde356e - * Thread=Thread-0 creating instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@6fde356e - * Thread=Thread-0 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@6fde356e - * Thread=Thread-3 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@6fde356e - * Thread=Thread-1 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@60f330b0 - * Thread=Thread-2 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@6fde356e - *
- * By changing the method signature of LazyLoadedIvoryTower#getInstance from - *
- * public static LazyLoadedIvoryTower getInstance() - *
- * into - *
- * public synchronized static LazyLoadedIvoryTower getInstance() - *
- * you should see the test output change to something like the following: - *
- * Thread=Thread-4 creating instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@3c688490
- * Thread=Thread-4 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@3c688490
- * Thread=Thread-0 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@3c688490
- * Thread=Thread-3 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@3c688490
- * Thread=Thread-2 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@3c688490
- * Thread=Thread-1 got instance=com.iluwatar.singleton.LazyLoadedSingletonThreadSafetyTest$LazyLoadedIvoryTower@3c688490
+ * This class provides several test case that test singleton construction.
+ *
+ * The first proves that multiple calls to the singleton getInstance object are the same when called in the SAME thread.
+ * The second proves that multiple calls to the singleton getInstance object are the same when called in the DIFFERENT thread.
*
*/
public class LazyLoadedSingletonThreadSafetyTest {
- private static final int NUM_THREADS = 5;
-
- @Test
- public void test() {
- SingletonThread runnable = new SingletonThread();
- for (int j=0; j