diff --git a/singleton/src/main/java/com/iluwatar/singleton/App.java b/singleton/src/main/java/com/iluwatar/singleton/App.java index d14088ca2..67cb6fd00 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/App.java +++ b/singleton/src/main/java/com/iluwatar/singleton/App.java @@ -1,51 +1,55 @@ -package com.iluwatar.singleton; - -/** - * - * Singleton pattern ensures that the class (IvoryTower) can have only one - * existing instance per java classloader instance and provides global access to it. - * - * http://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java - * - * The risk of this pattern is that bugs resulting from setting a singleton up in a distributed environment can - * be tricky to debug, since it will work fine if you debug with a single classloader. Additionally, these - * problems can crop up a while after the implementation of a singleton, since they may start out synchronous and - * only become async with time, so you it may not be clear why you are seeing certain changes in behaviour. - * - * http://stackoverflow.com/questions/17721263/singleton-across-jvm-or-application-instance-or-tomcat-instance - */ -public class App { - - public static void main(String[] args) { - - // eagerly initialized singleton - IvoryTower ivoryTower1 = IvoryTower.getInstance(); - IvoryTower ivoryTower2 = IvoryTower.getInstance(); - System.out.println("ivoryTower1=" + ivoryTower1); - System.out.println("ivoryTower2=" + ivoryTower2); - - // lazily initialized singleton - ThreadSafeLazyLoadedIvoryTower threadSafeIvoryTower1 = ThreadSafeLazyLoadedIvoryTower - .getInstance(); - ThreadSafeLazyLoadedIvoryTower threadSafeIvoryTower2 = ThreadSafeLazyLoadedIvoryTower - .getInstance(); - System.out.println("threadSafeIvoryTower1=" + threadSafeIvoryTower1); - System.out.println("threadSafeIvoryTower2=" + threadSafeIvoryTower2); - - // enum singleton - EnumIvoryTower enumIvoryTower1 = EnumIvoryTower.INSTANCE; - EnumIvoryTower enumIvoryTower2 = EnumIvoryTower.INSTANCE; - System.out.println("enumIvoryTower1=" + enumIvoryTower1); - System.out.println("enumIvoryTower2=" + enumIvoryTower2); - - InitializingOnDemandHolderIdiom demandHolderIdiom = InitializingOnDemandHolderIdiom.getInstance(); - System.out.println(demandHolderIdiom); - InitializingOnDemandHolderIdiom demandHolderIdiom2 = InitializingOnDemandHolderIdiom.getInstance(); - System.out.println(demandHolderIdiom2); - - ThreadSafeDoubleCheckLocking dcl1 = ThreadSafeDoubleCheckLocking.getInstance(); - System.out.println(dcl1); - ThreadSafeDoubleCheckLocking dcl2 = ThreadSafeDoubleCheckLocking.getInstance(); - System.out.println(dcl2); - } -} +package com.iluwatar.singleton; + +/** + * + * Singleton pattern ensures that the class ({@link IvoryTower}) can have only one + * existing instance per Java classloader instance and provides global access to it. + *
+ * http://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java + *
+ * The risk of this pattern is that bugs resulting from setting a singleton up in a distributed environment can + * be tricky to debug, since it will work fine if you debug with a single classloader. Additionally, these + * problems can crop up a while after the implementation of a singleton, since they may start out synchronous and + * only become async with time, so you it may not be clear why you are seeing certain changes in behaviour. + *
+ * http://stackoverflow.com/questions/17721263/singleton-across-jvm-or-application-instance-or-tomcat-instance + */ +public class App { + + /** + * Program entry point + * @param args command line args + */ + public static void main(String[] args) { + + // eagerly initialized singleton + IvoryTower ivoryTower1 = IvoryTower.getInstance(); + IvoryTower ivoryTower2 = IvoryTower.getInstance(); + System.out.println("ivoryTower1=" + ivoryTower1); + System.out.println("ivoryTower2=" + ivoryTower2); + + // lazily initialized singleton + ThreadSafeLazyLoadedIvoryTower threadSafeIvoryTower1 = ThreadSafeLazyLoadedIvoryTower + .getInstance(); + ThreadSafeLazyLoadedIvoryTower threadSafeIvoryTower2 = ThreadSafeLazyLoadedIvoryTower + .getInstance(); + System.out.println("threadSafeIvoryTower1=" + threadSafeIvoryTower1); + System.out.println("threadSafeIvoryTower2=" + threadSafeIvoryTower2); + + // enum singleton + EnumIvoryTower enumIvoryTower1 = EnumIvoryTower.INSTANCE; + EnumIvoryTower enumIvoryTower2 = EnumIvoryTower.INSTANCE; + System.out.println("enumIvoryTower1=" + enumIvoryTower1); + System.out.println("enumIvoryTower2=" + enumIvoryTower2); + + InitializingOnDemandHolderIdiom demandHolderIdiom = InitializingOnDemandHolderIdiom.getInstance(); + System.out.println(demandHolderIdiom); + InitializingOnDemandHolderIdiom demandHolderIdiom2 = InitializingOnDemandHolderIdiom.getInstance(); + System.out.println(demandHolderIdiom2); + + ThreadSafeDoubleCheckLocking dcl1 = ThreadSafeDoubleCheckLocking.getInstance(); + System.out.println(dcl1); + ThreadSafeDoubleCheckLocking dcl2 = ThreadSafeDoubleCheckLocking.getInstance(); + System.out.println(dcl2); + } +} diff --git a/singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java b/singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java index 329cd6a7e..4fd4c8163 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java +++ b/singleton/src/main/java/com/iluwatar/singleton/InitializingOnDemandHolderIdiom.java @@ -4,12 +4,12 @@ import java.io.Serializable; /** * The Initialize-on-demand-holder idiom is a secure way of - * creating lazy initialize singleton Object in Java. + * creating lazy initialized singleton object in Java. * refer to "The CERT Oracle Secure Coding Standard for Java" * By Dhruv Mohindra, Robert C. Seacord p.378 - * + *
* Singleton objects usually are heavy to create and sometimes need to serialize them. - * This class also shows how to preserve singleton in Serialized version of singleton. + * This class also shows how to preserve singleton in serialized version of singleton. * * @author mortezaadi@gmail.com * diff --git a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java index 352cac2e9..d15509236 100644 --- a/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java +++ b/singleton/src/main/java/com/iluwatar/singleton/ThreadSafeDoubleCheckLocking.java @@ -2,10 +2,11 @@ package com.iluwatar.singleton; /** * Double check locking - * + *
* http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html - * + *
* Broken under Java 1.4. + * * @author mortezaadi@gmail.com * */ diff --git a/singleton/src/test/java/com/iluwatar/singleton/AppTest.java b/singleton/src/test/java/com/iluwatar/singleton/AppTest.java index abe0440fd..c83232037 100644 --- a/singleton/src/test/java/com/iluwatar/singleton/AppTest.java +++ b/singleton/src/test/java/com/iluwatar/singleton/AppTest.java @@ -1,14 +1,19 @@ -package com.iluwatar.singleton; - -import org.junit.Test; - -import com.iluwatar.singleton.App; - -public class AppTest { - - @Test - public void test() { - String[] args = {}; - App.main(args); - } -} +package com.iluwatar.singleton; + +import org.junit.Test; + +import com.iluwatar.singleton.App; + +/** + * + * Application test + * + */ +public class AppTest { + + @Test + public void test() { + String[] args = {}; + App.main(args); + } +} diff --git a/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java b/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java index f40d8a319..ca88f4169 100644 --- a/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java +++ b/singleton/src/test/java/com/iluwatar/singleton/LazyLoadedSingletonThreadSafetyTest.java @@ -5,9 +5,9 @@ import org.junit.Test; /** * * 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 @@ -15,13 +15,17 @@ import org.junit.Test; * 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