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:每个类都有一个默认的构造方法。