1. 单例(Singleton)模式
一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建。
单例特点:
某个类只能有一个实例;(构造器私有)
它必须自行创建这个实例;(自己编写实例化逻辑)
它必须自行向整个系统提供这个实例;(对外提供实例化方法)
2. 懒汉模式
懒汉模式,即需要使用实例的时候再创建实例,时间换空间。
对象
public class Person {
private String name;
private String age;
//懒汉模式
private static Person instance;
// 1.保证构造私有,外部不能实例化
private Person() {
System.out.println("实例被创建了");
}
// 2.提供给外部的创建方法
public static Person create() {
// 懒汉模式 只有调用的时候才创建
if (instance == null) {
Person person = new Person();
instance = person;
}
return instance;
}
}
实例创建对象调用
public static void main(String[] args) {
Person person1 = Person.create();
Person person2 = Person.create();
System.out.println(person1 == person2); //ture
}
2.1. 线程安全
上方案例提供一个朴素的懒汉模式,不支持多线程,线程不安全,我们可以加静态的创建方法加上synchronized锁。
public static synchronized Person create() {
// 懒汉模式 只有调用的时候才创建
if (instance == null) {
Person person = new Person();
instance = person;
}
return instance;
}
但是我们在静态方法加上synchronized锁,这个锁又太大浪费资源,我们可以使用双重检查锁+内存可见性。
//懒汉模式
private volatile static Person instance;
public static Person create() {
// 懒汉模式 只有调用的时候才创建
if (instance == null) {
//加锁
synchronized (Person.class) {
//第二层验证
if (instance == null) {
Person person = new Person();
instance = person;
}
}
}
return instance;
}
3. 恶汉模式
饿汉模式,在加载到内存中的时候就初始化对象。
对象
//饿汉模式
private final static Person instance = new Person();
// 1.保证构造私有,外部不能实例化
private Person() {
System.out.println("实例被创建了");
}
// 2.提供给外部的创建方法
public static Person create() {
return instance;
}
4. 应用场景
什么场景用到?
多线程中的线程池
数据库的连接池
系统环境信息
上下文(ServletContext)
面试问题
系统环境信息(System.getProperties())?
- Spring中怎么保持组件单例的?
- ServletContext是什么(封装Servlet的信息)?是单例吗?怎么保证?
ApplicationContext是什么?是单例吗?怎么保证?
- ApplicationContext: tomcat:一个应用(部署的一个war包)会有一个应用上下文
- ApplicationContext: Spring:表示整个IOC容器(怎么保证单例的)。ioc容器中有很多组件(怎么保证单例)
- 数据库连接池一般怎么创建出来的,怎么保证单实例?