什么是单例模式

单例模式都有哪几种

饿汉模式,懒汉线程非安全模式,懒汉线程安全模式,内部类模式,枚举模式。现在最推荐的方式是枚举单例模式。

逐一介绍

饿汉模式:

/**
 * 饿汉式单例模式
 * 特点:可以通过反射机制攻击;线程安全[多个类加载器除外]。
 */
public class HungryType {
    public static final HungryType instance = new HungryType();
    
    private HungryType(){
        //初始化HungryType要做的事
    }
    
    public void splitAlipay() {
        System.out.println("饿汉式单利模式");
    }
    
    public static void main(String[] args) {
        HungryType ht =    HungryType.instance;
        ht.splitAlipay();
        
    }
}

懒汉线程非安全模式:

/**
 * 懒汉模式单例
 * 特点:延时加载;线程不安全,多线程下不能正常工作;
 */
public class SluggardType {
    private static SluggardType instance = null;
    
    private SluggardType() {
    
    }
    
    public static SluggardType getInstance(){
        if(instance == null){
            instance = new SluggardType();
        }
        return instance;
    }
    
    public void say(){
        System.out.println("懒汉模式单例");
    }
    
    public static void main(String[] args) {
        SluggardType.getInstance().say();
    }
}

懒汉线程安全模式(spring boot单例注入就用的这种模式):

/**
 * 懒汉模式(双重校验锁[不推荐])单例
 */
public class SluggardType2 {
    
    //volatile 关键字可以禁止指令重排 :可以确保instance = new SluggardType2()对应的指令不会重排序
    //但是因为对volatile的操作都在Main Memory中,而Main Memory是被所有线程所共享的,这里的代价就是牺牲了性能,无法利用寄存器或Cache
    private volatile static SluggardType2 instance = null;
    
    private SluggardType2(){
        
    }
    
    public static SluggardType2 getInstance(){
        if(instance == null){
            synchronized (SluggardType2.class) {
                if(instance == null){
                    instance = new SluggardType2();
                }
            }
        }
        
        return instance;
    }
    
    public void say(){
        System.out.println(" 懒汉模式(双重校验锁[不推荐])单例");
    }
    
    public static void main(String[] args) {
        SluggardType2.getInstance().say();
    }
    
    
}

内部类模式:

/**
 * 借助内部类实现单利模式:
 * 特点:既能实现延迟加载,又能实现线程安全
 */
public class InnerClassSingleton {
    /**
     * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例没有绑定关系,而且只有被调用到时才会装载(装在过程是由jvm保证线程安全)
     * ,从而实现了延迟加载
     */
    private static class SingletonHolder {
        /**
         * 静态初始化器,由JVM来保证线程安全
         */
        private static InnerClassSingleton instance = new InnerClassSingleton();
    }

    /**
     * 私有化构造方法
     */
    private InnerClassSingleton() {
    }

    /**
     * 这个模式的优势在于:getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本
     */
    public static InnerClassSingleton getInstance() {
        return SingletonHolder.instance;
    }

}

枚举模式:

/**
 * 枚举实现线程安全的单例模式:
 * 特点:JVM会保证enum不能被反射并且构造器方法只执行一次
 * 
 */
public class EnumSingleton {
    private EnumSingleton() {
    }

    public static EnumSingleton getInstance() {
        return Singleton.INSTANCE.getInstance();
    }

    private static enum Singleton {
        INSTANCE;

        private EnumSingleton singleton;

        // JVM会保证此方法绝对只调用一次
        private Singleton() {
            singleton = new EnumSingleton();
        }

        public EnumSingleton getInstance() {
            return singleton;
        }
    }
}

单例的好处

第一、控制资源的使用,通过线程同步来控制资源的并发访问;

第二、控制实例产生的数量,达到节约资源的目的。

第三、作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。
比如:Windows的垃圾回收站、文件管理、应用的数据库链接池等

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值