java 单例模式

java 单例模式

1.饿汉式

饿汉式存在内存浪费问题,没用到的时候实例直接就初始化了。

package com.yang;

public class Hungry {
    //单例模式构造函数必须私有
    private Hungry(){
        
    }
    public  static final Hungry hungry=new Hungry();//常量必须当时初始化
    public static Hungry getInstance(){
        return hungry;
    }
}

2.DCL懒汉式

懒汉式存在多线程并发问题。

package com.yang;

public class LazyMan {
    //私有构造
    private  LazyMan() {
    }

    private static  LazyMan lazyman;
    
    public static LazyMan getInstance(){
        if(lazyman==null){
            lazyman=new LazyMan();
        }
        return lazyman;
    }
}

多线程来同时第一次getInstance时可能都进入了函数中的if语句,导致构造函数多次调用。我们加上双重检测锁。就是所谓得DCL懒汉式。
双重检测锁第一层可以提升效率,免得后续getInstance每次都要锁类,导致效率低下,第二层检测锁是为了避免单例模式在多线程下的冲突。另外还要给私有变量加上原子操作。
volatile是java关键字,是轻量级的同步。有三大特性:

  • 保证可见性,即一个线程操作变量时,将主存中的变量值copy到自己线程的工作内存中,还没copy回去时,其他线程对该变量做出修改操作,此时本线程对该修改可见,
  • 不保证原子行,即一个线程对内存中变量操作时,从主存复制到自己的内存中还没复制回去时,其他线程可以对该资源做出修改,不安全。要想解决可以靠LOCK、synchornized,而更好的方式时 juc.atomic下的原子类,比如 AtomicInteger。其底层是CAS原理效率极高。
  • 禁止指令重排,防止编译器或者内存对我们的指令进行重新排序从而产生问题,原理是内存屏障。比如我们new一个对象的时候,1.分配内存空间、2.初始化对象、3.将引用指向该对象。而指令重排可能导致步骤为 1.3.2.这在我们的DCL懒汉式单例里面就会有问题。
public class LazyMan {
    //私有构造
    private  LazyMan() {
    }
    //volatile禁止指令重排,一个线程创建lazyman时,可能由于指令重排,引用已经指向内存地址了,
    //然而该内存对象还没初始化好,导致其他线程取到没初始化好的单例。
    private volatile static  LazyMan lazyman;
    //双重检测锁
    public static LazyMan getInstance(){
        if(lazyman==null){
            //拿到类锁,直接锁住该类
            synchronized (LazyMan.class){
                if(lazyman==null){
                    lazyman=new LazyMan();
                }
            }
        }
        return lazyman;
    }
}

3.静态内部类

内部类可以分为静态内部类和非静态内部类,,静态内部类由static修饰,可以包含静态成员,而非静态内部类不能包含静态成员。
定义静态内部类的时候,不需要绑定在外部类的实例上,即不需要new这个静态内部类,把它当成静态成员看待。
静态内部类相当于静态方法,只能访问外部类的静态成员,而非静态内部类可以访问外部类的所有成员。

public class LazyMan {
    //私有构造
    private  LazyMan() {
    }

    public static LazyMan getInstance(){
        return  innerClass.lazyman;
    }
    //静态内部类
    public static class innerClass{
        public static LazyMan lazyman=new LazyMan();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值