单例模式
- 单例模式
- 懒汉式
- 饿汉式
- 双重检验锁
- 静态内部类
- 枚举
单例模式
单例模式是java的创建型模式之一。
定义:单例模式能够防止频繁创建和销毁全局使用的类实例的问题,该模式确保一个类只有一个实例,并提供一个全局访问点来访问该实例。
特点:
- 1、单例类只能有一个实例;
- 2、单例类只能自己创建自己的唯一实例;
- 3、保证其他类对象能访问该实例。
单例模式的实现方式有多种:懒汉式、饿汉式、双重校验锁、静态内部类、枚举。
下面依次介绍单例模式的不同方式实现:
懒汉式
懒汉式即创建实例之后懒得初始化,等到方法使用时再初始化。
优点:第一次调用时才加载,防止内存浪费;
缺点:加锁影响效率
public class Singleton {//static关键字确保在所有调用中共享同一实例private static Singleton instance;//其他类无法创建本类实例private Singleton (){} //保证能全局访问,去掉锁就变成线程不安全的懒汉式public static synchronized Singleton getInstance() {//实例在第一次请求时才创建(延迟加载)if (instance == null) { instance = new Singleton(); } return instance; }
}
饿汉式
优缺点与懒汉式相反:不需要加锁,效率高;类加载时就创建单例实例,浪费内存。
public class Singleton {//在类加载时就创建单例实例private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; }
}
双重检验锁
优点:使用双锁机制,保证线程安全时还能保持高性能。
原理:使用volatile关键字防止指令重排序导致的线程安全问题,同时只在第一次初始化实例的时候加synchronized锁,后续调用不需要加锁,相比懒汉式每次调用实例都加锁大大提高了效率。
public class Singleton {// volatile 关键字确保实例的可见性和有序性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; }
}
静态内部类
这种方式只适用于静态域的情况,能达到双检锁方式一样的功效。
原理:只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。由于静态内部类只有第一次使用时才会被加载(类加载机制),也就无需检查实例。
public class Singleton { // 静态内部类,只有在第一次使用时才会被加载private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} // 提供全局访问点,通过内部类加载实现懒加载和线程安全public static final Singleton getInstance() { return SingletonHolder.INSTANCE; }
}
枚举
最简洁,自动支持序列化机制,绝对防止多次实例化。
原理:枚举类型的每一个实例都是 public static final 的,枚举类型的构造方法在类加载时被调用,并且每个枚举常量只被初始化一次。
public enum Singleton { INSTANCE; public void whateverMethod() { }
}