转自:https://blog.csdn.net/absolute_chen/article/details/93380566
单例模式,顾名思义就是只有一个实例,并且她自己负责创建自己的对象,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。下面我们来看下有哪几种实现方式吧。
核心代码:构造方法私有化,private。
1、懒汉式,线程不安全
/**
* 这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。
* 因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
*/
public class Singleton {
//构造函数私有化
private Singleton(){}
private static Singleton singleton = null;
//构建实例化方法
public static Singleton getSingleton(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
2、懒汉式,线程安全
/**
*
* 这种方式具备很好的 lazy loading,能够在多线程中很好的工作,
* 但是,效率很低,99% 情况下不需要同步。
* 优点:第一次调用才初始化,避免内存浪费。
* 缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
*/
public class Singleton {
//构造函数私有化
private Singleton(){}
private static Singleton singleton = null;
//构建实例化方法
public static synchronized Singleton getSingleton(){
if(singleton == null){
singleton = new Singleton();
}
return singleton;
}
}
3.饿汉式
/**
*
* 这种方式比较常用,但容易产生垃圾对象。
* 优点:没有加锁,执行效率会提高。
* 缺点:类加载时就初始化,浪费内存。
*/
class Singleton2 {
//私有构造函数
private Singleton2(){};
private static Singleton2 singleton2= new Singleton2();
public static Singleton2 getSingleton2(){
return singleton2;
}
}
4.双检锁/双重校验锁
/**
*
* 这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
*/
class Singleton3{
//私有构造函数
private Singleton3(){}
private static Singleton3 singleton3 = null;
public static Singleton3 getSingleton3(){
//先检查实例是否存在,如果不存在才进入下面的同步块
if(singleton3 == null){
//同步块,线程安全的创建实例
synchronized (Singleton3.class) {
//再次检查实例是否存在,如果不存在才真正的创建实例
if(singleton3 == null){
singleton3 = new Singleton3();
}
}
}
return singleton3;
}
}
5.静态(类级)内部类
/**
*
*实现更简单。
* 对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。
* 这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
*
*/
class Singleton4{
private Singleton4(){};
/**
*
* @Description: 类级内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
*
*/
private static class Singleton4Holder{
//静态初始化器,由JVM来保证线程安全
private static Singleton4 singleton4 = new Singleton4();
}
public static Singleton4 getSingleton4(){
return Singleton4Holder.singleton4;
}
}
6.单例和枚举
/**
*
* @Description: 枚举单例模式
*
*/
enum Singleton5{
SINGLETON5;
}
非常简洁,而且无偿地提供了序列化机制,并由JVM从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式。
enum有且仅有private的构造器,防止外部的额外构造,这恰好和单例模式吻合,也为保证单例性做了一个铺垫。