|
1 | | -/** |
2 | | - * Singleton pattern. |
3 | | - */ |
4 | | - |
5 | 1 | package com.iluwatar.singleton; |
6 | 2 |
|
7 | 3 | /** |
8 | | - * Singleton pattern ensures that the class ({@link IvoryTower}) can have only one |
9 | | - * existing instance per Java classloader instance and provides global access to it. |
| 4 | + * Singleton pattern ensures that the class can have only one existing instance per Java classloader instance |
| 5 | + * and provides global access to it. |
10 | 6 | * <p/> |
11 | | - * http://stackoverflow.com/questions/70689/what-is-an-efficient-way-to-implement-a-singleton-pattern-in-java |
12 | | - * <p/> |
13 | | - * The risk of this pattern is that bugs resulting from setting a singleton up in |
| 7 | + * One of the risks of this pattern is that bugs resulting from setting a singleton up in |
14 | 8 | * a distributed environment can be tricky to debug, since it will work fine if you |
15 | 9 | * debug with a single classloader. Additionally, these problems can crop up a while |
16 | 10 | * after the implementation of a singleton, since they may start out synchronous and |
17 | 11 | * only become async with time, so you it may not be clear why you are seeing certain |
18 | 12 | * changes in behaviour. |
19 | 13 | * <p/> |
20 | | - * http://stackoverflow.com/questions/17721263/singleton-across-jvm-or-application-instance-or-tomcat-instance |
| 14 | + * There are many ways to implement the Singleton. The first one is the eagerly initialized instance in |
| 15 | + * {@link IvoryTower}. Eager initialization implies that the implementation is thread safe. If you can |
| 16 | + * afford giving up control of the instantiation moment, then this implementation will suit you fine. |
| 17 | + * <p/> |
| 18 | + * The other option to implement eagerly initialized Singleton is enum based Singleton. The example is |
| 19 | + * found in {@link EnumIvoryTower}. At first glance the code looks short and simple. However, you should |
| 20 | + * be aware of the downsides including committing to implementation strategy, extending the enum class, |
| 21 | + * serializability and restrictions to coding. These are extensively discussed in Stack Overflow: |
| 22 | + * http://programmers.stackexchange.com/questions/179386/what-are-the-downsides-of-implementing-a-singleton-with-javas-enum |
| 23 | + * <p/> |
| 24 | + * {@link ThreadSafeLazyLoadedIvoryTower} is a Singleton implementation that is initialized on demand. |
| 25 | + * The downside is that it is very slow to access since the whole access method is synchronized. |
| 26 | + * <p/> |
| 27 | + * Another Singleton implementation that is initialized on demand is found in {@link ThreadSafeDoubleCheckLocking}. It |
| 28 | + * is somewhat faster than {@link ThreadSafeLazyLoadedIvoryTower} since it doesn't synchronize the whole access method |
| 29 | + * but only the method internals on specific conditions. |
| 30 | + * <p/> |
| 31 | + * Yet another way to implement thread safe lazily initialized Singleton can be found in {@link InitializingOnDemandHolderIdiom}. |
| 32 | + * However, this implementation requires at least Java 8 API level to work. |
21 | 33 | */ |
22 | 34 | public class App { |
23 | 35 |
|
@@ -48,16 +60,18 @@ public static void main(String[] args) { |
48 | 60 | System.out.println("enumIvoryTower1=" + enumIvoryTower1); |
49 | 61 | System.out.println("enumIvoryTower2=" + enumIvoryTower2); |
50 | 62 |
|
| 63 | + // double checked locking |
| 64 | + ThreadSafeDoubleCheckLocking dcl1 = ThreadSafeDoubleCheckLocking.getInstance(); |
| 65 | + System.out.println(dcl1); |
| 66 | + ThreadSafeDoubleCheckLocking dcl2 = ThreadSafeDoubleCheckLocking.getInstance(); |
| 67 | + System.out.println(dcl2); |
| 68 | + |
| 69 | + // initialize on demand holder idiom |
51 | 70 | InitializingOnDemandHolderIdiom demandHolderIdiom = |
52 | 71 | InitializingOnDemandHolderIdiom.getInstance(); |
53 | 72 | System.out.println(demandHolderIdiom); |
54 | 73 | InitializingOnDemandHolderIdiom demandHolderIdiom2 = |
55 | 74 | InitializingOnDemandHolderIdiom.getInstance(); |
56 | 75 | System.out.println(demandHolderIdiom2); |
57 | | - |
58 | | - ThreadSafeDoubleCheckLocking dcl1 = ThreadSafeDoubleCheckLocking.getInstance(); |
59 | | - System.out.println(dcl1); |
60 | | - ThreadSafeDoubleCheckLocking dcl2 = ThreadSafeDoubleCheckLocking.getInstance(); |
61 | | - System.out.println(dcl2); |
62 | 76 | } |
63 | 77 | } |
0 commit comments