单例模式

使用场景

只需要单个实例,比如说线程池、缓存等,如果存在两个不同的实例,就会引发种种问题。单例模式的设计就是为了保持永远只有一个实例。但是由于性能、存储上的考虑,单例模式有以下几种实现方式,可根据应用场景自行选择。

demo1 普通模式

public class Singleton {
    private static SingleTon uniqueInstance;

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

demo2 延迟实例化模式

public class Singleton {
    private static SingleTon uniqueInstance;

    //添加synchronized防止两个线程同时进入到该方法
    //避免实例化过程进行两次
    private synchronized static Singleton getInstance() {
        if (uniqueInstance == null) {
            uniqueInstance = new Singleton();
        }
        return uniqueInstance;
    }
}

demo3 急切实例化模式

public class Singleton {
    //保证线程安全,但是JVM在加载这个类时会马上创建实例
    //对性能会产生影响
    private static SingleTon uniqueInstance = new Singleton();

    private static Singleton getInstance() {
        return uniqueInstance;
    }
}

demo4 双重检查加锁

public class Singleton {
    //volatile确保变量被初始化后,多个线程能正确的处理该变量
    private volatile static SingleTon uniqueInstance;
    
    private static Singleton getInstance() {
        if (uniqueInstance == null) {
            //避免单例被初始化两次
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

关键点

  1. 私有的构造器
  2. 一个静态方法和一个静态变量

需要注意的点

  1. 在性能和资源的限制下选择最合适的方案

特定环境下的问题

  1. Java1.2之前, 单例没有全局引用时会被垃圾回收器回收, 1.2之后已经修复.
  2. 每个类加载器都定义了一个命名空间, 如果有多个类加载器, 就有可能会将一个类加载多次, 产生多个单例并存的情况. 解决办法: 自行指定类加载器, 并指定同一个类加载器.

你可能感兴趣的:(单例模式)