1. 概念
- 保证一个类只有一个实例
- 并为该实例提供一个全局唯一的访问节点
2. 双重检查
2.1 代码示例
示例
java
/**
* @Description: 静态内部类:懒加载,并且线程安全
*/
public class Singleton07 {
private Singleton07() {}
/**
* 写一个静态内部类,该类中有一个静态属性
*/
private static class SingletonInstance {
private static final Singleton07 INSTANCE = new Singleton07();
}
/**
* 提供一个静态的公有方法,直接返回SingletonInstance.IINSTANCE
* @return Singleton07
*/
public static Singleton07 getInstance() {
return SingletonInstance.INSTANCE;
}
}
java
public class SingletonTest07 {
public static void main(String[] args) {
Singleton07 instance = Singleton07.getInstance();
Singleton07 instance1 = Singleton07.getInstance();
System.out.println(instance == instance1);
System.out.println("instance.hashCode= " + instance.hashCode());
System.out.println("instance1.hashCode= " + instance1.hashCode());
}
}
2.2 优缺点
- 这种方式采用了类装载的机制来保证初始化实例时只有一个线程
- 静态内部类方式在Singleton类被装载时并不会立即实例化,而是在需要实例化时,调用getinstance方法,才会装载SingletonInstance类,从而完成Singleton的实例化。
- 类的静态属性只会在第一次加载类的时候初始化,所以在这里JVM帮助我们保证了线程的安全性,在类进行初始化时,别的线程是无法进入的。
- 避免了线程不安全,利用静态内部类特点实现延迟加载,效率高。
2.3 结论
- 线程安全,延迟加载,效率高,在实际开发中,推荐使用这种单例设计模式。
3. 题外篇:静态内部类
3.1 加载时机
- 静态内部类是在程序中调用静态内部类的时候加载的,和外部类的加载没有必然关系。但是如果在加载静态内部类的时候发现外部类还没有加载,那么就会先加载外部类,加载完外部类之后,再加载静态内部类。如果在程序中单纯的使用外部类,并不会触发静态内部类的加载