package com.doctor.design_pattern.singleton; /** * @author sdcuike * * Created on 2016年7月31日 下午11:36:05 * * 饿汉式 单例 * EagerInitialized Singleton */ public class EagerInitializedSingleton { private static final EagerInitializedSingleton instance = new EagerInitializedSingleton(); private EagerInitializedSingleton() { } public static EagerInitializedSingleton getInstance() { return instance; } public void doSomething() { System.out.println("test"); } public static void main(String[] args) { System.out.println(EagerInitializedSingleton.getInstance()); System.out.println(EagerInitializedSingleton.getInstance()); EagerInitializedSingleton.getInstance().doSomething(); // com.doctor.design_pattern.singleton.EagerInitializedSingleton@2a139a55 // com.doctor.design_pattern.singleton.EagerInitializedSingleton@2a139a55 // test System.out.println(EagerInitializedSingleton.getInstance() == EagerInitializedSingleton.getInstance()); // true } }
package com.doctor.design_pattern.singleton; /** * @author sdcuike * * Created on 2016年8月1日 上午12:30:08 */ public class StaticBlockSingleton { private static StaticBlockSingleton instance; public static StaticBlockSingleton getInstance() { return instance; } static { try { instance = new StaticBlockSingleton(); } catch (Exception e) { throw new RuntimeException("Exception occured in creating singleton instance"); } } public static void main(String[] args) { System.out.println(StaticBlockSingleton.getInstance()); System.out.println(StaticBlockSingleton.getInstance()); System.out.println(StaticBlockSingleton.getInstance() == StaticBlockSingleton.getInstance()); // com.doctor.design_pattern.singleton.StaticBlockSingleton@2a139a55 // com.doctor.design_pattern.singleton.StaticBlockSingleton@2a139a55 // true } }
package com.doctor.design_pattern.singleton; /** * @author sdcuike * * Created on 2016年8月1日 上午12:39:40 */ public class LazyInitializedSingleton { private static LazyInitializedSingleton instance; public static LazyInitializedSingleton getInstance() { if (instance == null) { instance = new LazyInitializedSingleton(); } return instance; } private LazyInitializedSingleton() { } public static void main(String[] args) { System.out.println(LazyInitializedSingleton.getInstance() == LazyInitializedSingleton.getInstance());// true } }
/** * @author sdcuike * * Lazy initialization method to implement Singleton pattern creates the * instance in the global access method. Here is the sample code for * creating Singleton class with this approach. Created on 2016年8月1日 * 上午12:39:40 * * @see http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples * 懒初始化,多线程会导致破坏单例原则 */ public class LazyInitializedSingleton { private static LazyInitializedSingleton instance; /** * 为了模拟多线程情况下的问题,加入了休眠时间 * * @return */ public static LazyInitializedSingleton getInstance() { try { Thread.sleep((long) (Math.random() * 100)); } catch (InterruptedException e) { e.printStackTrace(); } if (instance == null) { try { Thread.sleep((long) (Math.random() * 100)); } catch (InterruptedException e) { e.printStackTrace(); } instance = new LazyInitializedSingleton(); try { Thread.sleep((long) (Math.random() * 100)); } catch (InterruptedException e) { e.printStackTrace(); } } return instance; } private LazyInitializedSingleton() { } public static void main(String[] args) { // System.out.println(LazyInitializedSingleton.getInstance() == // LazyInitializedSingleton.getInstance());// true ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.submit(() -> { System.out.println(LazyInitializedSingleton.getInstance()); }); } executorService.shutdown(); // com.doctor.design_pattern.singleton.LazyInitializedSingleton@6a1bb74 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@6a1bb74 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@6a1bb74 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@2be16806 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@2be16806 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@5f93f536 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@5f93f536 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@5f93f536 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@5f93f536 // com.doctor.design_pattern.singleton.LazyInitializedSingleton@46d3a9 // 得到的实例并不是同一个。 } }
synchronized
package com.doctor.design_pattern.singleton; /** * @author sdcuike * * Created on 2016年8月1日 上午11:19:36 * * Thread Safe Singleton * */ public class ThreadSafeSingleton { private static ThreadSafeSingleton instance; public static synchronized ThreadSafeSingleton getInstance() { if (instance == null) { instance = new ThreadSafeSingleton(); } return instance; } private ThreadSafeSingleton() { } public static void main(String[] args) { System.out.println(ThreadSafeSingleton.getInstance() == ThreadSafeSingleton.getInstance()); // true } }
package com.doctor.design_pattern.singleton; /** * @author sdcuike * * Created on 2016年8月1日 上午11:37:25 * * double checked locking principle */ public class DoubleCheckedLockingThreadSafeSingleton { private static DoubleCheckedLockingThreadSafeSingleton instance; public static DoubleCheckedLockingThreadSafeSingleton getInstance() { if (instance == null) { synchronized (DoubleCheckedLockingThreadSafeSingleton.class) { if (instance == null) { instance = new DoubleCheckedLockingThreadSafeSingleton(); } } } return instance; } private DoubleCheckedLockingThreadSafeSingleton() { } public static void main(String[] args) { } }
/** * @author sdcuike * * Created on 2016年8月1日 上午11:37:25 * * double checked locking principle and volatile variable */ public class DoubleCheckedLockingThreadSafeSingleton { private static volatile DoubleCheckedLockingThreadSafeSingleton instance; /** * double check的目的是为了进步一获得线程安全,第一步check为null的时候可能先后进来两个线程访问,此时单例还没初始化, * 这个时候开始上锁,如果前一个线程上锁后初始化了这个单例而释放锁,那后边的线程也可以锁定对象,然后初始化, * 这样就违背了单例原则,所以我们在锁住对象后又进一步check对象是否初始化了。 * 不过,由于java内存的可见性问题(java内存模型),一个线程初始化了对象,double * check的时候,并不一定能时时判断实例是否被另一个线程初始化了,所以上面的代码还是有线程安全问题的, * 所以我们必须在实例变量声明的时候加上关键字volatile,使得多线程对变量的修改能时时的让其他线程看到这个结果。 * * @return */ public static DoubleCheckedLockingThreadSafeSingleton getInstance() { if (instance == null) { synchronized (DoubleCheckedLockingThreadSafeSingleton.class) { if (instance == null) { instance = new DoubleCheckedLockingThreadSafeSingleton(); } } } return instance; } private DoubleCheckedLockingThreadSafeSingleton() { } public static void main(String[] args) { } }
package com.doctor.design_pattern.singleton; /** * @author sdcuike * * Inner static helper class Singleton * * * Created on 2016年8月1日 上午11:54:05 */ public class InnerStaticHelperClassSingleton { private InnerStaticHelperClassSingleton() { } public static InnerStaticHelperClassSingleton getInstance() { return SingletonHelper.instance; } private static class SingletonHelper { private static final InnerStaticHelperClassSingleton instance = new InnerStaticHelperClassSingleton(); } public static void main(String[] args) { } }
package com.doctor.design_pattern.singleton; /** * @author sdcuike * * Enum Singleton * 枚举实现单例不能延迟加载资源,但保证了enum值只实例化一次。而且克服了反射带来的问题 * * Created on 2016年8月1日 下午12:24:06 */ public enum EnumSingleton { instance; private EnumSingleton() { } public void doSomething() { System.out.println("test do "); } public static void main(String[] args) { EnumSingleton.instance.doSomething(); } }
protected Object readResolve() { return getInstance(); }
public static void main(String[] args) throws ReflectiveOperationException, SecurityException { System.out.println(EagerInitializedSingleton.getInstance()); System.out.println(EagerInitializedSingleton.getInstance()); EagerInitializedSingleton.getInstance().doSomething(); // com.doctor.design_pattern.singleton.EagerInitializedSingleton@2a139a55 // com.doctor.design_pattern.singleton.EagerInitializedSingleton@2a139a55 // test System.out.println(EagerInitializedSingleton.getInstance() == EagerInitializedSingleton.getInstance()); // true // 反射破坏 Constructor<EagerInitializedSingleton> constructor = EagerInitializedSingleton.class.getDeclaredConstructor(); constructor.setAccessible(true); EagerInitializedSingleton newInstance = constructor.newInstance(); System.out.println(newInstance); }
com.doctor.design_pattern.singleton.EagerInitializedSingleton@15db9742 com.doctor.design_pattern.singleton.EagerInitializedSingleton@15db9742 test true com.doctor.design_pattern.singleton.EagerInitializedSingleton@6d06d69c
/** * 反射导致单例失败:How to fix: Throw Runtime Exception if someone tries to make * instance in case one instance already exists. This code will go into the * private constructor of the Singleton class */ private EagerInitializedSingleton() { if (instance != null) { throw new RuntimeException("plean use getInstance() method"); } }
com.doctor.design_pattern.singleton.EagerInitializedSingleton@15db9742 com.doctor.design_pattern.singleton.EagerInitializedSingleton@15db9742 test true Exception in thread "main" java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at com.doctor.design_pattern.singleton.EagerInitializedSingleton.main(EagerInitializedSingleton.java:57) Caused by: java.lang.RuntimeException: plean use getInstance() method at com.doctor.design_pattern.singleton.EagerInitializedSingleton.<init>(EagerInitializedSingleton.java:31) ... 5 more
public class EagerInitializedSingleton implements Cloneable { private static final EagerInitializedSingleton instance = new EagerInitializedSingleton(); /** * 反射导致单例失败:How to fix: Throw Runtime Exception if someone tries to make * instance in case one instance already exists. This code will go into the * private constructor of the Singleton class */ private EagerInitializedSingleton() { if (instance != null) { throw new RuntimeException("plean use getInstance() method"); } } public static EagerInitializedSingleton getInstance() { return instance; } public void doSomething() { System.out.println("test"); } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } public static void main(String[] args) throws ReflectiveOperationException, SecurityException, CloneNotSupportedException { System.out.println(EagerInitializedSingleton.getInstance()); System.out.println(EagerInitializedSingleton.getInstance()); EagerInitializedSingleton.getInstance().doSomething(); // com.doctor.design_pattern.singleton.EagerInitializedSingleton@2a139a55 // com.doctor.design_pattern.singleton.EagerInitializedSingleton@2a139a55 // test System.out.println(EagerInitializedSingleton.getInstance() == EagerInitializedSingleton.getInstance()); // true // 反射破坏 // Constructor<EagerInitializedSingleton> constructor = // EagerInitializedSingleton.class.getDeclaredConstructor(); // constructor.setAccessible(true); // EagerInitializedSingleton newInstance = constructor.newInstance(); // System.out.println(newInstance); // 克隆破坏 EagerInitializedSingleton eagerInitializedSingleton = EagerInitializedSingleton.getInstance(); EagerInitializedSingleton eagerInitializedSingletonClone = (EagerInitializedSingleton) eagerInitializedSingleton.clone(); System.out.println(eagerInitializedSingleton + "==" + eagerInitializedSingletonClone + " is " + (eagerInitializedSingleton == eagerInitializedSingletonClone)); } }
克隆破坏: com.doctor.design_pattern.singleton.EagerInitializedSingleton@15db9742==com.doctor.design_pattern.singleton.EagerInitializedSingleton@6d06d69c is false
@Override protected Object clone() throws CloneNotSupportedException { if (instance != null) { throw new CloneNotSupportedException("plean use getInstance() method"); } return super.clone(); }
http://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples
JAVA DESIGN PATTERNS By Devendra Singh @Copyright 2016 Dev S