单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,该模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。
注意:
- 作用:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
- 主要解决:一个全局使用的类频繁地创建与销毁。
- 何时使用:当您想控制实例数目,节省系统资源的时候。
- 关键代码:构造函数是私有的。
实现方式:
(1)饿汉模式:线程安全、调用效率高、但不能延时加载
class Singleton_Hungry{
private static Singleton_Hungry instance = new Singleton_Hungry();
// 构造器私有化
private Singleton_Hungry(){};// 创造公有方法调用instance
public static Singleton_Hungry getSingleton(){
return instance;
}
}
直接把单例对象创建出来了,要用的时候直接返回即可。但是问题也比较明显。单例在还没有使用到的时候,初始化就已经完成了。也就是说,如果程序从头到位都没用使用这个单例的话,单例的对象还是会创建。这就造成了不必要的资源浪费。所以不推荐这种实现方式。
好处是没有线程安全的问题,坏处是浪费内存空间。
(2)懒汉模式:线程安全,调用效率不高,但是能延时加载
public class Singleton_Lazy {
//类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)
private static Singleton_Lazy instance;//构造器私有化
private Singleton_Lazy(){}//方法同步,调用效率低
public static synchronized Singleton_Lazy getInstance(){
if(instance==null){
instance=new Singleton_Lazy();
}
return instance;
}
}
优点: 只有在使用时才会实例化单例,一定程度上节约了资源。
缺点: 第一次加载时要立即实例化,反应稍慢。每次调用getInstance()方法都会进行同步,这样会消耗不必要的资源。这种模式一般不建议使用。
(3)静态内部类:线程安全,调用效率高,能延时加载
public class Singleton_static { private Singleton_static() { } // 静态内部类 private static class SingletonHolder { private static Singleton_static instance = new Singleton_static(); } public static Singleton_static getInstance() { return SingletonHolder.instance; } }
第一次加载Singleton类时不会初始化instance,只有在第一次调用getInstance()方法时,虚拟机会加载SingletonHolder类,初始化instance。
(4)枚举类:线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用
public enum Singleton_enum { //枚举元素本身就是单例 INSTANCE; //添加自己需要的操作 public void singletonOperation(){ } }
默认枚举实例的创建是线程安全的,即使反序列化也不会生成新的实例,任何情况下都是一个单例。简单。
(5)Double CheckLock(双重锁判断机制):线程安全,能延时加载
public class Singleton{ private static volatile Singleton singleton; private Singleton(){}; private static Singleton getSingleton(){ if(singleton==null){ // 改进加锁懒汉式,锁加在if判断语句后,可减少锁的使用 synchronized(Singleton.class){ if(singleton==null){ singleton=new Singleton(); } } } return singleton; } }
双重锁判断机制,综合了懒汉式和饿汉式两者的优缺点整合而成。看上面代码实现中,特点是在synchronized关键字内外都加了一层 if 条件判断,这样既保证了线程安全,又比直接上锁提高了执行效率,还节省了内存空间。