一.什么是单例以及单例的使用场景就很少说了,不清楚的能够看我上篇文章或者自行查找安全
二.单例和多并发之间的规则并发
单例就是只能建立一个实例对象,而多并发状况下若是不处理一下单例的写法很难保证只建立一个实例对象,因此后面会出问题jvm
处理的思路:在建立对象的时候使用同步锁,或者直接懒人作法---放一个静态的实例对象函数
三.几种常见的单例模式的写法spa
1.最常规的(线程不安全--不支持多并发)线程
public class Singleton { //一个静态的实例 private static Singleton singleton; //私有化构造函数 private Singleton(){} //给出一个公共的静态方法返回一个单一实例 public static Singleton getInstance(){ if (singleton == null) { singleton = new Singleton(); } return singleton; }
2.上面的经常使用的是不支持并发的,因此后面考虑在方法上加同步锁,可是若是在上面那个获取对象的方法上加锁则会每次在获取对象时都须要等待,蛮费时间的,因此不能这么玩,code
可使用以下方法内部类写法(其实我感受他和饿汉式差很少,都是new一个静态实例放在那里)对象
public class Singleton { /* 私有构造方法,防止被实例化 */ private Singleton() { } /* 此处使用一个内部类来维护单例 */ private static class SingletonFactory { private static Singleton instance = new Singleton(); } /* 获取实例 */ public static Singleton getInstance() { return SingletonFactory.instance; } } 备注: 第一次调用getInstance的时候,JVM可以帮咱们保证instance只被建立一次,而且会保证把赋值给instance的内存初始化完毕,由于JVM内部的机制可以保证当一个类被加载的时候,这个类的加载过程是线程互斥的 能够对比一下饿汉式写法: public class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; } }
3.或者在建立类的那个时刻同步就行,获取对象的方法就不一样步(和懒汉式相似,须要时加载就行)blog
public class SingletonTest { private static SingletonTest instance = null; private SingletonTest() { } private static synchronized void syncInit() { if (instance == null) { instance = new SingletonTest(); } } public static SingletonTest getInstance() { if (instance == null) { syncInit(); } return instance; } } 懒汉式的不高效写法,至关于也是同步了获取对象的方法 public class Singleton { private static Singleton instance; private Singleton(){} public static synchronized Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return instance; } }
4.所谓的双重锁写法(至关于变相的在类的建立时加同步锁,和方法三原理相似或者和方法二内部类利用jvm类加载机制相似)内存
public class Singleton{ private volatile static Singleton singleton; private Singleton(){} public static Singleton getSingleton(){ if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }