支持多并发的单例有哪几种写法
一.什么是单例以及单例的使用场景就不多说了,不清楚的可以看我上篇文章或者自行查找
二.单例和多并发之间的规则
单例就是只能创建一个实例对象,而多并发情况下如果不处理一下单例的写法很难保证只创建一个实例对象,所以后面会出问题
处理的思路:在创建对象的时候使用同步锁,或者直接懒人做法---放一个静态的实例对象
三.几种常见的单例模式的写法
1.最常规的(线程不安全--不支持多并发)
public class Singleton { //一个静态的实例 private static Singleton singleton; //私有化构造函数 private Singleton(){} //给出一个公共的静态方法返回一个单一实例 public static Singleton getInstance(){ if (singleton == null) { singleton = new Singleton(); } return singleton; }
2.上面的常用的是不支持并发的,所以后面考虑在方法上加同步锁,但是如果在上面那个获取对象的方法上加锁则会每次在获取对象时都需要等待,蛮费时间的,所以不能这么玩,
可以使用如下方法内部类写法(其实我感觉他和饿汉式差不多,都是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.或者在创建类的那个时刻同步就行,获取对象的方法就不同步(和懒汉式类似,需要时加载就行)
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; } }