单例模式懒汉式和饿汉式

本文探讨了Java中的两种单例模式实现:饿汉式和懒汉式。饿汉式在类加载时即完成初始化,保证线程安全但不延迟加载;懒汉式在首次调用getInstance时初始化,非线程安全,可通过synchronized关键字解决。双重校验锁(DCL)实现延迟加载并确保线程安全,但可能存在指令重排问题,使用volatile关键字可避免。此外,还介绍了静态内部类方式,兼顾线程安全和延迟加载。
摘要由CSDN通过智能技术生成

饿汉式(线程安全)

public class SingletonEH {
    private static SingletonEH instance = new SingletonEH();
    private SingletonEH() {

    }

    public static SingletonEH getInstance() {
        System.out.println("instance:" + instance);
        System.out.println("加载饿汉式");
        return instance;
    }
}

在饿汉式中,只要类加载完成,就把单例化初始化完成了。保证在getInstance的时候,单例已经是存在的。

懒汉式(非线程安全)

public class SingletonLH {
    private static SingletonLH instance;

    private SingletonLH() {

    }

    public static SingletonLH getInstance() {
        if (instance == null) {
            instance = new SingletonLH();
        }
        return instance;
    }
}

懒汉式比较懒,只有当调用getInstance的时候,才会对单例进行初始化

懒汉式非线程安全的解决办法就是在getInstance方法上添加synchronized就可以了

public class SingletonLHSync {
    private static SingletonLHSync instance;
    
    private SingletonLHSync() {
        
    }
    
    public static synchronized SingletonLHSync getInstance() {
        if (instance == null) {
            instance = new SingletonLHSync();
        }
        return instance;
    }
}

饿汉式和懒汉式的比较
在这里插入图片描述

双重校验锁

  • 加锁的懒汉式单例模式虽然可以保证线程安全,又实现了延迟加载,但是会影响效率
  • synchronized修饰的方法执行较慢,如果多次调用getInstance就会造成性能下降
public class Singleton {
    private static Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance() {
        if (instance == null) {   // Single Checked
            synchronized (Singleton.class) {
                if (instance == null) { // Double checked
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  • 同步代码块外层多了一层if判断,由于单例对象只需要创建一次,所以以后如果调用getInstance,就直接返回单例对象
  • 大部分情况下,调用getInstance方法,都不会运行到同步代码块,从而保证性能提高
  • 但是由于Java的指令重排,所以还是会有隐患

解决方案:

使用volatile变量,禁止指令重排

public class Singleton {
    private static volatile Singleton instance = null;
    private Singleton(){}
    public static Singleton getInstance() {
        if (instance == null) { // Single Checked
            synchronized (Singleton.class) {
                if (instance == null) { // Double checked
                    instance = new Singleton();
                }
 
            }
        }
        return instance;
    }
}

静态内部类

public class Singleton{
    private static class SingletonHolder{
        public static Singleton instance = new Singleton();
    }
    private Singleton(){}
    public static Singleton newInstance(){
        return SingletonHolder.instance;
    }
}
  • 单例对象是在静态内部类中创建
  • 其与饿汉式一样,利用类加载机制,保证线程安全
  • 如果不调用静态内部类,就不会初始化单例对象,实现类似懒汉式的延迟加载

参考 Links:

单例模式懒汉式和饿汉式区别

Java单例模式的不同写法(懒汉式、饿汉式、双检锁、静态内部类、枚举)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值