单例模式

  1 package com.study;
  2 
  3 import java.io.ObjectStreamException;
  4 import java.io.Serializable;
  5 import java.util.Objects;
  6 
  7 /**
  8  * 单例模式
  9  * 1、类的创建模式,创建对象的最优方式,例如spring中管理的bean大部分为单例。
 10  * 2、单例要素:
 11  * 全局唯一的对象实例
 12  * 单例类自己创建唯一的实例(禁止客户端调用创建)
 13  * 单例类必须对外暴露(提供)获取对象实例的方法
 14  * 导致单一实例失败问题:
 15  * 1、调用反射,进行实例化
 16  * 2、反序列化导致实例不一致
 17  * 3、线程安全
 18  */
 19 
 20 public class Singleton {
 21     public static void main(String[] args) {
 22         SingletonEnum instance = SingletonEnum.SINGLETON;
 23         instance.doSomething();
 24     }
 25 }
 26 
 27 /**
 28  * 饿汉 单例模式
 29  * 即类加载就创建对象(并非调用getInstance时候加载,可能调用其他静态方法导致类加载),由类加载机制提供线程安全保障
 30  * 优点:简单安全高效
 31  * 缺点:不确定对象是否需要使用
 32  */
 33 class SingletonNormal implements Serializable {
 34     private static SingletonNormal singleton = new SingletonNormal();
 35 
 36     /**
 37      * 1、将构造函数设置为私有的避免被new对象,破坏单一实例
 38      */
 39     private SingletonNormal() {
 40         //避免通过反射调用创建对象
 41         if (!Objects.isNull(singleton)) {
 42             throw new RuntimeException("实例已存在");
 43         }
 44     }
 45 
 46     /**
 47      * 反序列化时候直接返回singleton实例,不需要重新实例化一个对象实例,避免反序列化造成多个实例
 48      *
 49      * @return
 50      * @throws ObjectStreamException
 51      */
 52     private Object readResolve() throws ObjectStreamException {
 53         return singleton;
 54     }
 55 
 56 
 57     /**
 58      * 返回实例
 59      *
 60      * @return
 61      */
 62     public static SingletonNormal getInstance() {
 63         return singleton;
 64     }
 65 
 66     /**
 67      * 如果通过SingletonNormal.test()导致类加载,实例化对象,此时的instance并非真正需要,导致浪费内存
 68      */
 69     public static void test() {
 70         //do ...
 71     }
 72 }
 73 
 74 /**
 75  * 懒汉  单例模式
 76  * 用于弥补实例消耗资源,将实例延迟到需要使用的时候创建的方案
 77  * 优点:仅在通过调用SingletonLazy.getInstance()时候才会创建对象
 78  * 缺点:因为同步方法,导致效率下降
 79  */
 80 class SingletonLazy {
 81     private static SingletonLazy singleton;
 82 
 83     private SingletonLazy() {
 84         //避免通过反射调用创建对象
 85         if (!Objects.isNull(singleton)) {
 86             throw new RuntimeException("实例已存在");
 87         }
 88     }
 89 
 90     /**
 91      * 同步方法避免并发情况下创建多个实例
 92      *
 93      * @return
 94      */
 95     public static synchronized SingletonLazy getInstance() {
 96         if (Objects.isNull(singleton)) {
 97             singleton = new SingletonLazy();
 98         }
 99         return singleton;
100     }
101 }
102 
103 /**
104  * 双重校验锁,主要用于弥补高并发下懒汉式的效率低下的方案 (不建议使用)
105  * 优点:提升效率
106  * 缺点:实现复杂,由于编译器优化等原因可能导致失败
107  */
108 class SingletonDCL {
109     private static volatile SingletonDCL singleton = null;//volatile用于解决可见性问题
110 
111     private SingletonDCL() {
112         //避免通过反射调用创建对象
113         if (!Objects.isNull(singleton)) {
114             throw new RuntimeException("实例已存在");
115         }
116     }
117 
118     /**
119      * 锁住类对象
120      *
121      * @return
122      */
123     public static SingletonDCL getInstance() {
124         if (Objects.isNull(singleton)) {
125             SingletonDCL instance;
126             synchronized (SingletonDCL.class) {
127                 instance = singleton;
128                 if (Objects.isNull(instance)) {
129                     synchronized (SingletonDCL.class) {
130                         instance = new SingletonDCL();
131                     }
132                 }
133             }
134             singleton = instance;
135         }
136         return singleton;
137     }
138 }
139 
140 /**
141  * 内部类单例模式
142  * 通过定义内部类,然后由外表调用内部类的时候加载,由类加载保障安全
143  * 优点:高效、延迟加载
144  */
145 class SingletonInner {
146     private static SingletonInner singleton;
147 
148     private SingletonInner() {
149         //避免通过反射调用创建对象
150         if (!Objects.isNull(singleton)) {
151             throw new RuntimeException("实例已存在");
152         }
153     }
154 
155     /**
156      * 执行Singleton.INSTANCE时才会对内部类进行加载
157      */
158     private static class Singleton {
159         private static final SingletonInner INSTANCE = new SingletonInner();
160     }
161 
162     public static SingletonInner getInstance() {
163         return Singleton.INSTANCE;
164     }
165 }
166 
167 /**
168  * 枚举式单例(推荐使用)
169  * 由JVM保障安全/反序列化/反射等问题
170  * 优点:简单、高效、安全
171  * <p>
172  * SingletonEnum instance = SingletonEnum.SINGLETON;
173  */
174 enum SingletonEnum {
175     SINGLETON;
176 
177     public void doSomething() {
178         System.out.println("这是最佳的单例实现模式....");
179     }
180 }

 

posted @ 2019-04-14 09:26  MigrantWorkers  阅读(85)  评论(0编辑  收藏  举报