应用场景:
-
读取配置文件的类
-
数据库连接池
-
Spring 创建的实例,默认为单例
共同点:一个类只有一个实例,将构造方法私有化,并且提供一个公共的方法访问该类的实例对象。
实现方式:常见的有两种,饿汉式 & 懒汉式
1.饿汉式
/** * 饿汉式 * */ public class SingletonDemo1 { private static SingletonDemo1 instance = new SingletonDemo1(); private SingletonDemo1() { } public static SingletonDemo1 getInstance() { return instance; } }
特点:线程安全,不用加锁,但是不能懒加载,浪费资源。
2.懒汉式(线程不安全)
/** * 懒汉式(线程不安全) * */ public class SingletonDemo2 { private static SingletonDemo2 instance; private SingletonDemo2() { } public static SingletonDemo2 getInstance() { if(instance == null){ instance = new SingletonDemo2(); } return instance; } }
特点:实现了懒加载,但是线程不安全
3.懒汉式(线程安全)
/** * 懒汉式(线程安全) * */ public class SingletonDemo3 { private static SingletonDemo3 instance; private SingletonDemo3() { } public static synchronized SingletonDemo3 getInstance() { if(instance == null){ instance = new SingletonDemo3(); } return instance; } }
特点:实现了懒加载,线程安全,是对上一种方案的优化,但是需要添加同步锁,高并发时调用效率不高。
4.懒汉式(线程安全 双重校验锁)
/** * 懒汉式(线程安全 双重校验锁) * */ public class SingletonDemo4 { private static SingletonDemo4 instance; private SingletonDemo4() { } public static SingletonDemo4 getInstance() { if(instance == null){ synchronized (SingletonDemo4.class) { if(instance == null){ instance = new SingletonDemo4(); } } } return instance; } }
特点:线程安全&&实现了懒加载,而且在使用同步锁之前先做判断,提升效率。
5.静态内部类
/** * 静态内部类 * */ public class SingletonDemo5 { private static class SingletonHolder{ private static final SingletonDemo5 instance = new SingletonDemo5(); } private SingletonDemo5() { } public static final SingletonDemo5 getInstance() { return SingletonHolder.instance; } }
特点:外部类没有静态属性,因此不会像饿汉式立即加载对象。
只有当调用公共方法(getInstance)时,才会加载静态内部类。加载内部类的过程是线程安全的。
内部类中通过 static final 确保内存中只有一个外部类的实例,因为实例变量(instance)只能被赋值一次。
综上所述,一般采用第四种跟第五种方式实现单例模式。