1. 单例(Singleton)模式

一个单一的类,负责创建自己的对象,同时确保系统中只有单个对象被创建。

单例特点:

  • 某个类只能有一个实例;(构造器私有)

  • 它必须自行创建这个实例;(自己编写实例化逻辑)

  • 它必须自行向整个系统提供这个实例;(对外提供实例化方法)
    03. 单例(Singleton)模式 - 图1

2. 懒汉模式

懒汉模式,即需要使用实例的时候再创建实例,时间换空间。

对象

  1. public class Person {
  2. private String name;
  3. private String age;
  4. //懒汉模式
  5. private static Person instance;
  6. // 1.保证构造私有,外部不能实例化
  7. private Person() {
  8. System.out.println("实例被创建了");
  9. }
  10. // 2.提供给外部的创建方法
  11. public static Person create() {
  12. // 懒汉模式 只有调用的时候才创建
  13. if (instance == null) {
  14. Person person = new Person();
  15. instance = person;
  16. }
  17. return instance;
  18. }
  19. }

实例创建对象调用

  1. public static void main(String[] args) {
  2. Person person1 = Person.create();
  3. Person person2 = Person.create();
  4. System.out.println(person1 == person2); //ture
  5. }

2.1. 线程安全

上方案例提供一个朴素的懒汉模式,不支持多线程,线程不安全,我们可以加静态的创建方法加上synchronized锁。

  1. public static synchronized Person create() {
  2. // 懒汉模式 只有调用的时候才创建
  3. if (instance == null) {
  4. Person person = new Person();
  5. instance = person;
  6. }
  7. return instance;
  8. }

但是我们在静态方法加上synchronized锁,这个锁又太大浪费资源,我们可以使用双重检查锁+内存可见性。

  1. //懒汉模式
  2. private volatile static Person instance;
  3. public static Person create() {
  4. // 懒汉模式 只有调用的时候才创建
  5. if (instance == null) {
  6. //加锁
  7. synchronized (Person.class) {
  8. //第二层验证
  9. if (instance == null) {
  10. Person person = new Person();
  11. instance = person;
  12. }
  13. }
  14. }
  15. return instance;
  16. }

3. 恶汉模式

饿汉模式,在加载到内存中的时候就初始化对象。

对象

  1. //饿汉模式
  2. private final static Person instance = new Person();
  3. // 1.保证构造私有,外部不能实例化
  4. private Person() {
  5. System.out.println("实例被创建了");
  6. }
  7. // 2.提供给外部的创建方法
  8. public static Person create() {
  9. return instance;
  10. }

4. 应用场景

  • 什么场景用到?

    • 多线程中的线程池

    • 数据库的连接池

    • 系统环境信息

    • 上下文(ServletContext)

    • 面试问题

  • 系统环境信息(System.getProperties())?

    • Spring中怎么保持组件单例的?
    • ServletContext是什么(封装Servlet的信息)?是单例吗?怎么保证?
    • ApplicationContext是什么?是单例吗?怎么保证?

      • ApplicationContext: tomcat:一个应用(部署的一个war包)会有一个应用上下文
      • ApplicationContext: Spring:表示整个IOC容器(怎么保证单例的)。ioc容器中有很多组件(怎么保证单例)
    • 数据库连接池一般怎么创建出来的,怎么保证单实例?