单例模式

单利模式有很多种实现方式,每一种方式都有自己合适的场合。常用的单利有:懒汉式、饿汉式、线程安全式、双重检查式和登记式。实现单利最重要的一点是构造方法是private的,这使得实例不能被外界所创建。

懒汉式

这是最简单的一种单利模式,但是带来的问题是线程不安全。这里所谓的不安全是指在创建第一个实例时是线程不安全的。可以看到,当我们初次使用时才会创建实例,所以叫懒汉式。

public class SimpleSingleton {

    private static SimpleSingleton simpleSingleton;

    //必须为private,这是实例独一无二的保证
    private SimpleSingleton(){

    }

    public static SimpleSingleton getInstance(){
        //如果不存在则实例一个
        if(simpleSingleton==null){
            //创建第一个实例时是线程不安全的
            simpleSingleton = new SimpleSingleton();
        }
        return simpleSingleton;
    }
}

线程安全式

为了解决线程安全的问题,我们只需要在获得实例的方法上同步即可,但是这就会造成程序性能下降。

public class SafeSingleton {

    private static SafeSingleton safeSingleton;

    // 必须为private,这是实例独一无二的保证
    private SafeSingleton() {

    }

    //保证线程安全
    public static synchronized SafeSingleton getInstance() {
        // 如果不存在则实例一个
        if (safeSingleton == null) {
            safeSingleton = new SafeSingleton();
        }
        return safeSingleton;
    }
}

饿汉式

可以看到,在JVM加载这个类时,就会创建实例。JVM能保证在任何线程访问到eagerSingleton实例之前将其创建完成。

public class EagerSingleton {

    //JVM加载这个类时就创建
    private static EagerSingleton eagerSingleton = new EagerSingleton();

    private EagerSingleton(){};

    public static EagerSingleton  getInstance(){
        return eagerSingleton;
    }
}

双重检查

线程安全式中,同步了整个getInstance方法才保证了线程安全,会浪费很多性能。于是我们可以使用双重检查式,它将只在初次创建实例的时候实现同步。(了解锁优化的同学可以理解为减少锁的颗粒度)

public class DoubleCheckSingleton {

    private volatile static DoubleCheckSingleton doubleCheckSingleton;

    private DoubleCheckSingleton() {
    };

    public static DoubleCheckSingleton getInstance() {
        //这里没有加synchronized
        if (doubleCheckSingleton == null) {
            //很多线程都能到达这里
            synchronized (DoubleCheckSingleton.class) {
                //有可能已经有线程更早一步创建了单利
                if (doubleCheckSingleton == null)
                    doubleCheckSingleton = new DoubleCheckSingleton();
            }
        }
        return doubleCheckSingleton;
    }
}

登记式

虽然和饿汉式一样使用了静态域,但是此种方式的实例加载是Lazy的。

public class StaticSingleton {

    // 利用了 classloder 机制来保证初始化 instance 时只有一个线程
    private static class SingletonHolder {
        private static final StaticSingleton INSTANCE = new StaticSingleton();
    }

    private StaticSingleton() {
    }

    public static final StaticSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值