一. 含义
- 单例模式就是通过将构造方法设为私有,通过提供的静态getInstance方法返回某个对象的唯一实例。就是一个对象的唯一一个实例由单例类掌控。该类负责创建单例并提供全局访问点。
二. 实现
-
普通单例模式
- 实现方法:
public class Singleton { private static Singleton sSingleton;//唯一实例 /*私有构造方法,保证了外部无法创建类的实例*/ private Singleton() { } /*通过该方法获取唯一实例*/ public static Singleton getInstance() { if (sSingleton == null) { sSingleton = new Singleton(); } return sSingleton; } }
- 缺点:
- 遇到多线程的时候就不能保证只有单一实例了
如何解决遇到多线程时不能保证只有一个实例呢?就引出了以下方法:
-
加了同步锁的单例模式
- 实现:
public class Singleton { private static Singleton sSingleton;//唯一实例 /*私有构造方法,保证了外部无法创建类的实例*/ private Singleton() { } /*通过该方法获取唯一实例,添加了synchronized关键字,确保一次只能有一个线程执行该方法*/ public static synchronized Singleton getInstance() { if (sSingleton == null) { sSingleton = new Singleton(); } return sSingleton; } }
- 缺点:
- 其实只有当第一次创建单例是才需要互斥,后面就不用了,但是互斥锁却一直存在,严重降低性能
- 即刻实例化,而不是延迟实例化
- 实现:
public class Singleton { private static Singleton sSingleton = new Singleton();//不管用不用的到,在程序一开始就执行静态初始化,直接初始化实例,就不会存在多个实例的问题了 private Singleton() { } public static Singleton getInstance() { return sSingleton; } }
- 缺点:
- 要是不确定用不用的到,就会造成资源浪费
-
双重检查加锁的单例模式
- 实现:
public class Singleton { private volatile static Singleton sSingleton;//volatile确保了初始化后多线程能正确处理该实例 private Singleton() { } public static Singleton getInstance() { if (sSingleton == null) {//检查实例,若不存在就进入同步区,这样就保证了只有第一次才进行同步 synchronized (Singleton.class) { if (sSingleton == null) { sSingleton = new Singleton(); } } } return sSingleton; } }
- 缺点:
- JDK1.5之前JVM对volatile关键字的实现会导致双重检查加锁失效
三. 总结
- 要是不考虑多线程,则第一种方式就可以实现单例模式。
- 第二种模式严重降低性能,若对单例使用较少,影响较低则可使用
- 第三种实现有点奇怪,但是如果能确定一定会用到单例的话,使用该方法最好。
- 第四种实现起来较为复杂,但算是完美的解决方案了。
网友评论