1. 单例模式

属于设计模式的一种,常见的设计模式有23种,如单例模式、模板模式、策略模式、工厂模式、代理模式。

设计模式:就是一种设计思想,针对一些常见场景出现的问题,总结的一些通用解决方法。

一个程序,可以创建多个类的实例。

单例模式:一个程序里,只能创建一个实例(即一个类只有一个实例)。单个实例的设计模式。

2. 单例模式的经典实现

(1)懒汉模式:用不到这个实例就不创建,用的时候再去创建、实例化。

步骤:先把构造方法改成私有的;创建一个实例,不进行初始化;对外提供一个方法,来获取这个实例并进行初始化(当外部调用这个方法时,此时再去进行初始化)。

PS:实例的初始化其实只需一次,也就是第一次。只需要第一个线程对该实例进行初始化即可,后面的线程只需要直接获取前面这个实例就可以。

/**
 * 懒汉模式
 * 1.构造函数私有化
 * 2。正确加锁
 * 3.双重check
 * 4.volatile
 * 目标:实现一个线程安全的单例模式
 */
public class Singleton2 {
    private Singleton2(){}
    private  static volatile Singleton2 instance=null;//加上volatile可以禁止指令的重排序
    public static Singleton2 getInstance(){
        if(instance==null){//1.  null 是判断是否加锁,当instance!=null时,两个线程同时访问,就不需要进行锁的竞争-->是性能考虑
            //要进行加锁--> 要满足单例模式,加锁的对象一定是唯一的,即一个程序里只有一个对象,才能保证多线程访问时,是对同一个对象进行加锁的
            synchronized(Singleton2.class){//类对象,一个程序只有一个,这是JVM保证的
                //类文件编译后是一个class文件,这个class被jvm加载到内存就是一个对象。这个对象里包含了类的各种信息,如类的成员、类的方法等
                if(instance==null){//2.  此处的instance是避免重复实例化,线程安全-->这两个判断互相不能替代,这两个判断也叫双重check (double-check)
                    instance=new Singleton2();
                }
            }
        }
        return  instance;
    }
}

(2)饿汉模式:先提前把实例创建出来、初始化,用的时候就可以直接拿出来用。

步骤:先把这个默认的构造方法改成私有的,也就是在其他地方不能创建实例;提前创建出一个实例并进行初始化;提供一个方法来获取这个实例。

/**
 * 饿汉模式
 * 1.默认构造函数初始化
 * 2.创建一个实例并实例化
 * 3.提供一个方法让其他程序使用
 */
public class Singleton {
    private Singleton(){}//构造方法私有化
                         //如果不把它改为private,那么其他类就可以通过new sington()来创建实例,就没法保证只有一个实例
    private static  Singleton  instance=new Singleton();//创建一个实例并进行初始化,整个程序只有这一个实例
    public static Singleton getInstance(){//其他类只能通过getInstance来获取这个实例.static修饰的方式就是类方法,不属于某一个实例。
        return instance;
    }
}

PS:每个类都有一个默认的构造方法。