什么是单例模式
单例模式确保一个类只有一个实例,并提供一个全局访问点,实现单例模式的方法是私有化构造函数,通过getInstance()方法实例化对象,并返回这个实例
保证在JVM中只有一个实例 幂等 JVM中如何保证实例的幂等问题 保证唯一性
饿汉、懒汉 双重检验
单例模式优缺点
1、单例类只有一个实例 2、共享资源,全局使用 3、节省创建时间,提高性能
缺点:可能存在线程不安全的问题 解决线程安全问题
如何破解单例
代码语言:javascript复制 public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Constructor<SingletionV5> declaredConstructor = SingletionV5.class.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
SingletionV5 singletionV5 = declaredConstructor.newInstance();
}
饿汉式
代码语言:javascript复制/**
* 饿汉式 优点:先天性 线程安全,当类初始化的时候,就会创建对象
* 缺点:如果项目使用过多的饿汉式,会发生问题。越多启动越慢,存放方法去占用内存比较大
*/
public class SingletionV1 {
private static SingletionV1 singletionV1=new SingletionV1();
//1。单例模式 是否可以让程序员 初始化
private SingletionV1() {
}
public SingletionV1 getInstance(){
return singletionV1;
}
}
懒汉式
代码语言:javascript复制public class SingletionV2 {
//懒汉式 当真正需要的时候才被初始化
private static SingletionV2 SingletionV2;
private SingletionV2() {
}
/**
* 线程不安全,多线程情况下,可能会初始化多次
* @return
*/
public static SingletionV2 getInstance(){
if (SingletionV2 == null) {
SingletionV2=new SingletionV2();
}
return SingletionV2;
}
}
双重检验锁
代码语言:javascript复制/**
* 双重检验锁,解决懒汉式 线程安全问题,
*/
public class SingletionV3 {
private static SingletionV3 SingletionV3;
/**
* 双重检验锁 读不加锁,写的时候加锁
*/
public SingletionV3 getSingletionV3(){
// 当多个线程同时new对象的时候,才会加锁。保证线程安全。
if (SingletionV3 == null) {
//只有一个对象 初始化
synchronized (SingletionV3.class){
if (SingletionV3 == null) { // 当前线程 已经获取到锁了,
SingletionV3 = new SingletionV3();
}
}
}
return SingletionV3;
}
private SingletionV3() {
}
}
静态内部类
代码语言:javascript复制/**
* 静态内部类
* 特征:继承懒汉式的优点。同时解决双重检验锁
*/
public class SingletionV5 {
private SingletionV5() {
}
//在 类里面 嵌套一个类
private static class SingletionV5Utils{
private static final SingletionV5 singletionV5=new SingletionV5();
}
public static SingletionV5 getSingleton(){
return SingletionV5Utils.singletionV5;
}
}
枚举
代码语言:javascript复制public enum EnumSingleton {
INSTANCE;
// 枚举能够绝对有效的防止实例化多次,和防止反射和序列化破解
public void add() {
System.out.println("add方法...");
}
}