设计模式 —— 单例模式

单例模式有很多种实现方式,目的是为了控制类的实例个数,确保一个类只有一个实例

在23种设计模式中,单例模式可以说是最简单的一种了,实现它的要素有如下几点:

  • 私有的构造方法(不让外部实例化)
  • 私有的静态实例(给公有静态方法调用)
  • 公有的静态访问方法

常见的单例模式有以下几种:

  • 饿汉式
    一开始就创建一个类的实例(不管有没有被用到),不存在线程安全问题,第一次比较慢
public class Singleton{
    //私有的构造方法
    private Single(){}
    //私有的静态实例
    private static Singleton instance = new Singleton();
    //共有的静态访问方法
    public static Singleton getInstance(){
        return instance;
    }
}
  • 懒汉式
    程序需要的时候再去加载(体现延迟加载思想,所以叫懒汉式)
public class Singleton{
    //私有构造方法
    private Singleton(){}
    //私有静态实例
    private static Singleton instance;
    //公有的静态访问方法
    public static Singleton getInstance(){
        if(instance == null){
            //需要的时候才实例化
            instance = new Singleton();
        }
        return instance;
    }
}

这种方法有线程安全问题,在多线程情况下,容易实例化多个实例
为了解决线程安全问题,我们可以使用synchronized关键字,保证一个线程访问时,其他线程的访问被堵塞

public class Singleton{
    //私有构造方法
    private Singleton(){}
    //私有静态实例
    private static Singleton instance;
    //公有的静态访问方法
    //使用synchronized保证线程安全
    public static synchronized Singleton getInstance(){
        if(instance == null){
            //需要的时候才实例化
            instance = new Singleton();
        }
        return instance;
    }
}

这种方法也有弊端,容易造成阻塞时间过长的问题

为了改善这个问题,可以把synchronized放在if条件语句内

public class Singleton{
    //私有构造方法
    private Singleton(){}
    //私有静态实例
    private static Singleton instance;
    //公有的静态访问方法
    public static Singleton getInstance(){
        if(instance == null){
            synchronized(Singleton.class){
                //双重校验
                if (instance == null) { 
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

或者加/解锁

        if(instance == null){
            //加锁
            lock.lock();
            if(instance ==null){
                instance = new Singleton();
            }
            //解锁
            lock.unlock();
        }

终极方式(推荐使用)

public class Singleton{
    //私有构造方法
    private Singleton(){}
    //在私有的静态内部类中进行私有的静态实例化
    private static class Psc{
        private static final Singleton INSTANCE = new Singleton();
    }
    //公有的静态访问方法
    public static synchronized Singleton getInstance(){
        return Psc.INSTANCE;
    }
}

这种方式利用类的加载机制,静态块代码只加载一次,同时也避免了多线程的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值