单例模式总结

描述

Singleton Pattern:

Ensure a class has only one instance, and provide a global point of access to it.(确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。)

实现

懒汉式

// 经典实现方式
public class Singleton{
    // 唯一实例,私有并且静态
    private static Singleton uniqueInstance;
    // 私有化构造器
    private Singleton(){}
    // 静态方法 获取单例
    public static Singleton getInstance(){
        // 懒汉式,如果我们不需要这个实例,它就永远不会产生
        if (uniqueInstance == null){
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}

缺点:线程不安全

如果两个线程同时调用 getInstance() 方法,同时进入if语句,那么就会创造两个实例

懒汉式—加锁

public class Singleton{
    private static Singleton uniqueInstance;
    private Singleton(){}
    //通过增加 synchronized 关键字到 getInstance 方法,使得不会有两个线程同时进入这个方法。
    public static Synchronized Singleton getInstance(){
        if (uniqueInstance == null){
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}

缺点:性能差

每次调用 getInstance() 都会加锁

懒汉式— DCL 双重锁

public class Singleton{
    // volatile 关键字确保 当uniqueInstance 变量被初始化成 Singleon实例时
    // 多个线程正确地处理uniqueInstance变量
    private volatile static Singleton uniqueInstance;
    private Singleton(){}
    public static Singleton getInstance(){
        // 检查实例,如果不存在,则进入同步区块,如果存在,直接返回
        if(uniqueInstance == null){// 只有第一次才会彻底执行这里的代码块
            Synchronized(Singleton.class){
                if(uniqueInstance == null){//进入区块后,再检查一次,如果仍是null,才创建实例
                    uniqueInstance = new Singleton;
                }
            }
        }
        return uniqueInstance;
    }
}

优点:大大减少getInstance() 方法的时间耗费

饿汉式

天然线程安全

public class Singleton{
    private static Singleton uniqueInstance = new Singleton();
    private Singleton(){}
    public static getInstance(){
        return uniqueInstance;
    }
}

扩展

写一个多例模式

public class MultiPattern{
    // 必须要有容器
    private static List<Chess> chessList = new ArrayList<>();
    private static final Chess whiteChess = new Chess("white");
    private static final Chess blackChess = new Chess("black");
    private static final int maxCount = 2;

    static{
        chessList.add(whiteChess);
        chessList.add(blackChess);
    }

    // 私有化构造器
    private MultiPattern(){}

    public static Chess getInstance(){
        Random random = new Random();
        int crt = random.nextInt(maxount);
        return chessList.get(crt);
    }
    public static Chess getInstance(int index){
        return chessList.get(index);
    }
}

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

爬取B站弹幕并分析 上一篇
「面试」SAP 下一篇