单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
适⽤场景: 单例模式只允许创建⼀个对象,因此节省内存,加快对象访问速度,因此对象需要被公⽤的场 合适合使⽤,如多个模块使⽤同⼀个数据源连接对象等等。如:
- 需要频繁实例化然后销毁的对象。
- 创建对象时耗时过多或者耗资源过多,但⼜经常⽤到的对象。
- 有状态的⼯具类对象。
- 频繁访问数据库或⽂件的对象。
一、饿汉式
/**
* @author GodLiang
* @version 1.0
* @date 2021/2/9 17:12
* @description: TODO 单例模式 饿汉式
*/
public class HungrySingleton {
//在类加载时创建对象。且一直不会被回收
private static HungrySingleton hungrySingleton = new HungrySingleton();
//防⽌反射获取多个对象的漏洞
private HungrySingleton() {
if (null != hungrySingleton)
throw new RuntimeException();
}
public static HungrySingleton getSingletonBean() {
return hungrySingleton;
}
}
饿汉式优缺点
优点: 没有加锁,执行效率会提高。
缺点: 类加载时就初始化,浪费内存。
二、懒汉式
双重校验锁:
/**
* @author GodLiang
* @version 1.0
* @date 2021/2/9 17:17
* @description: TODO 单例模式 懒汉式
*/
public class LazySingleton {
//加volatile 实现可见性。其他线程创建好对象后马上同步到其他线程,并禁止指令重排
private volatile static LazySingleton lazySingleton;
private LazySingleton() {
//禁止反射创建对象
if (null != lazySingleton) {
throw new RuntimeException("禁止反射");
}
System.out.println("c初始化");
}
public static LazySingleton getLazySingleton() {
//这里的是为了避免每次进来都加锁。如果不为空则创建过了,不需要加锁。解决效率问题
if (null == lazySingleton) {
synchronized (LazySingleton.class) {
//进来再判断一次。防止堵塞在锁处。多次创建示例
if (null == lazySingleton) {
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
public static void main(String[] args) throws IllegalAccessException, InstantiationException, InterruptedException {
for (int i = 0; i < 10; i++) {
new Thread(() -> {
LazySingleton singletonBean = LazySingleton.getLazySingleton();
}).start();
}
LazySingleton.class.newInstance();
}
}
优缺点
- 优点: 第一次调用才初始化,避免内存浪费。
- 缺点: 必须加锁 synchronized和volatile 才能保证单例,但加锁会影响效率。
其他懒汉略。。。