设计模式千千万,总是单例最常见。
单例模式的定义
保障一个类仅有一个实例,并提供一个拜访它的全局拜访点。
六种单例的创立形式
1.饿汉式
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; }}
长处:
基于类的加载机制,防止了多线程同步问题,加载速度快。
毛病:
在类加载的时候就实现初始化,没有懒加载,如果没有应用这个实例,会造成内存节约。
2.懒汉式-线程不平安版
public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if(instance == null){ instance = new Singleton(); } return instance; }}
长处:
第一次调用是才初始化对象,避免浪费资源
毛病:
加载速度慢,线程不平安
3.懒汉式-线程平安版(synchronized加锁)
public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if(instance == null){ instance = new Singleton(); } return instance; }}
长处:
多线程中保障线程平安
毛病:
每次获取对象实例,都须要进行同步,造成不必要的同步开销。
4.双重校验锁
public class Singleton { private static volatile Singleton instance; private Singleton() {} public static Singleton getInstance() { if(instance == null){ synchronized(Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; }}
长处:
线程平安,懒加载,缩小同步开销
毛病:
第一个获取对象速度稍慢,但其在某些状况下也会呈现生效的状况,并不是完满的形式。
这外面应用了两次判空:第一次为了不必要的加锁同步,第二次是确保在instance为null的状况下才创立实例,防止屡次创立。
办法中还是用了关键字volatile对变量进行润饰,有如下几个作用:
1.在Java内存模型中volatile能够保障可见性,及避免程序指令重排序。
2.对象的创立分为如下几个步骤:
instance = new Singleton();
- 1.为instance分配内存空间
- 2.初始化instance
- 3.将instance指向内存地址
如果不加volatile的话,程序的执行程序就可能变成1->3->2,多线程中就会导致线程获取一个没有初始化的实例。例如线程a 执行了1,3, 此时线程b调用getInstance()发现instance不为空,返回instance,但此时instance还未初始化。
5.动态外部类
public class Singleton { private Singleton() {} public static Singleton getInstance() { return SingletonHolder.sInstance; } private static class SingletonHolder { private static final Singleton sInstance = new Singleton(); }}
第一次加载类的时候不会初始化instance,只有第一次调用getInstance()的时候才会进行加载SingleHolder并初始化instance,保障线程平安,也能保障实例惟一,举荐应用这种形式。
6.枚举
public enum Singleton {INSTANCE;public void doSomeThing(){}}
默认枚举单例的创立是线程平安的,并且任何状况下都是单例。
以上就是6中常见的单例创立模式,按需应用吧。
单例的应用场景
- 整个我的项目须要一个共享拜访点或者数据
- 创立一个对象须要消耗的资源太多,比方拜访数据库资源等
- 工具类对象