单例模式定义:
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
单例模式特点:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式的核心:
无论使用该类方法多少次,都只产生一个该类对象,可以减少系统内存的消耗
单例模式实现方式:
1、立即加载的单例模式----饿汉模式
public class Singleton {
private Singleton(){}
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
}
类加载时,会直接实例化单例对象,以后都返回该对象的引用,当构造方法私有化后,无法在当前类的外部去通过构造方法产生对象 。
优点:没有加锁,执行效率高,线程安全的实例。
缺点:类加载时,会直接实例化单例对象,不管我有没有使用到该单例对象,浪费内存。
2、延迟加载的单例模式----懒汉模式
public class LazySingleton {
private LazySingleton(){}
private volatile static LazySingleton singleton;
public static LazySingleton getInstance(){
if(singleton == null){
singleton = new LazySingleton();
}
return singleton;
}
单线程情况下,是安全的,不要直接在类加载时实例化,而是在调用方法时,再实例化。
优点:不会占用内存。
缺点:线程不安全。
在多线程下,多个线程可能同时执行singleton == null都为true,会创建多个实例在内存中,可通过双重检验 首先先判断实例是否为null,为null则使用synchronized锁住类 ,然后在同步块中,再一次判断实例是否为null,为null则初始化实例。
public static LazySingleton getInstance(){
if(singleton == null){
synchronized (LazySingleton.class){
if(singleton == null){
singleton = new LazySingleton();
}
}
}
return singleton;
}
}
3、静态内部类
public class InnerSingleton {
private InnerSingleton(){}
private static class Inner{
private static InnerSingleton instance = new InnerSingleton();
}
public static InnerSingleton getInstance(){
return Inner.instance;
}
}
通过静态内部类 完成单例模式的创建,在外部类加载时,并不会加载内部类,也就是不会执行new 实例(),只有第一次调用getInstance方法时,才会加载,这也属于懒加载模式。
优点:不用考虑线程的安全问题。
缺点:一开始就创建,如果没有使用此对象将会造成内存空间的浪费。
4、静态代码块
public class Singleton {
private Singleton(){}
private static Singleton singleton = null;
static {
singleton = new Singleton();
}
public static Singleton getInstance(){
return singleton;
}
}
5、枚举创建
public class EnumSingleton {
private EnumSingleton(){}
private static enum SinEnum{
TEST;
private EnumSingleton es = new EnumSingleton();
}
public static EnumSingleton getInstance(){
SinEnum s = SinEnum.TEST;
return s.es;
}
}
优点:线程安全,只会加载一次,节省系统资源。
以上是本文章介绍的单例模式的理解和实现,希望对所看到者有所帮助。