单例类
public class Singleton {
private static volatile Singleton instance;
public static Singleton newInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
解释
- 使用volatile可以保证创建单例时的原子性,此时如果两个线程同时请求该方法,其中一个线程已经到了new关键字处,而此时另外一个线程也去请求该方法,但是该实例并未实例化完整(实例化可能会很复杂,分多个步骤完成),所以另外一个线程返回的就是一个不完整的实例。
- 两次判断null(双重?):第一次判断可以防止直接加锁而阻断程序,影响性能。第二次判断是因为如果两个线程同时访问,而且此时实例为null,两个线程都通过了第一个if,但是其中的一个线程已经创建了实例,如果没有了第二次判断,则第二个线程还会继续创建一个新的实例。
- 加锁可保证只有一个线程访问创建实例
测试类
public class Main {
public static void main(String[] args) {
Singleton singleton = new Singleton();
new Thread(() -> System.out.println("线程——1——" + singleton.newInstance())).start();
new Thread(() -> System.out.println("线程——2——" + singleton.newInstance())).start();
}
}
运行截图