Java设计模式之单例模式

单例模式的几种方式:饿汉式单例,懒汉单例,双层校验锁单例,容器单例,静态内部类单例,枚举单例。

饿汉单例
/**
 * 饿汉单例(类加载的时候就获取实例)
 * 线程安全的
 */
public class SingleTon {
    private static SingleTon instance=new SingleTon();
    private SingleTon(){
    }
    public static SingleTon getInstance(){
        return instance;
    }
}
懒汉单例
/**
 * 懒汉单例(非线程安全)
 */
public class SingleTon {

    private static SingleTon instance;
    private SingleTon(){
    }
     public static SingleTon getInstance(){
        if (instance==null){
            instance=new SingleTon();
        }
        return instance;
    }
}
/**
 * 懒汉单例(线程安全)
 */
public class SingleTon {

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

在方法上加同步锁使得线程安全,但多线程访问方法每次都要等待锁的释放,这种方式性能太差。其实只需要在第一次实例化加锁就可以了,之后访问直接获取实例就好了。所以出现了双重检验锁单例模式。

双重校验锁单例
/**
 * 双重检验锁单例(线程安全)
 */
public class SingleTon {

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

1.第一个if 判断是否已经实例化,如果实例化则直接返回,不需要在执行同步锁,优化了性能。
2.第二个 if,多个线程通过第一个 if判断,其中一个线程先获得锁并实例化对象,当第一个线程释放锁后,之后获得锁的线程不会在实例化对象,直接返回实例。

这种方式仍然存在隐患,对象实例化分三个步骤:
1.分配内存空间
2.初始化对象
3.将对象指向刚分配的内存空间
编译器为了性能可能将2和3的顺序重排序:
1.分配内存空间
2.将对象指向刚分配的内存空间
3.初始化对象

A线程执行到2步骤时instance 不为空,B线程判断到 instance 不为空,直接返回 instance,但是此时 instance 还未被初始化。使用volatile关键字解决问题,禁止重排,所有的写(write)操作都将发生在读(read)操作之前。

public class SingleTon {

    private volatile static SingleTon instance;
    private SingleTon(){
    }
    public static SingleTon getInstance(){
        if (instance==null){
            synchronized (SingleTon.class){
                if (instance==null){
                    instance=new SingleTon();
                }
            }
        }
        return instance;
    }
}
容器单例
/**
 * 容器单例
 */
public class SingleTon {

    private static Map<String,Object> objMap=new HashMap<>();

    private SingleTon(){
    }

    public static void registerService(String key,Object instance){
        if (!objMap.containsKey(key)){
            objMap.put(key,instance);
        }
    }

    public static Object getService(String key){
           return objMap.get(key);
    }
}
静态内部类单例
public class SingleTon {

    private static class SingleTonHolder{
        private static final SingleTon instance=new SingleTon();

    private SingleTonHolder(){}
    }

    private SingleTon(){}

    public static SingleTon getInstance(){
        return SingleTonHolder.instance;
    }
}
枚举单例
public enum SingleTon{
        Singleton;
        private SingleTon1 singleton;
        //枚举类的构造方法在类加载是被实例化
        private SingleTon(){
            singleton = new SingleTon1();
        }
        public SingleTon1 getInstance(){
            return singleton;
        }
}

public class SingleTon1 {
    public SingleTon1(){}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值