1单例模式的UML图
注:本文中的UML图是根据自己的想法绘制的,并不是直接照抄,仅供学习参考
2.单例模式几种写法的比较
2.1 饿汉式
/**
* 饿汉式
* 类加载到内存后,就实例化一个单例,JVM保证线程安全
* 简单实用,推荐使用!
* 唯一缺点:不管用到与否,类装载时就完成实例化
*/
public class Singleton01 {
private static final Singleton01 INSTANCE = new Singleton01();
private Singleton01() {};
public static Singleton01 getInstance() {
return INSTANCE;
}
}
2.2懒汉式
/**
* lazy loading
* 也称懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
*/
public class Singleton2 {
private static Singleton2 INSTANCE;
private Singleton2() {
}
public static Singleton2 getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton2();
}
return INSTANCE;
}
}
2.3双重检查方式
/**
* lazy loading
* 也称懒汉式
* 虽然达到了按需初始化的目的,但却带来线程不安全的问题
* 可以通过synchronized解决,但也带来效率下降
*/
public class Singleton03 {
private static volatile Singleton03 INSTANCE;
private Singleton03() {
}
public static Singleton03 getInstance() {
if (INSTANCE == null) {
//双重检查
synchronized (Singleton03.class) {
if(INSTANCE == null) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Singleton03();
}
}
}
return INSTANCE;
}
}
2.4 枚举类单例
/**
* 不仅可以解决线程同步,还可以防止反序列化。
* [《通过枚举类创建线程池的应用》](https://blog.csdn.net/u011862409/article/details/109062993)
* 这篇文章就是枚举类单例的应用
*/
public enum Singleton04 {
INSTANCE;
public void m() {}
}
2.5 静态内部类的方式
/**
* 静态内部类方式
* JVM保证单例
* 加载外部类时不会加载内部类,这样可以实现懒加载
*/
public class Singleton05 {
private Singleton05() {
}
private static class Mgr07Holder {
private final static Singleton05 INSTANCE = new Singleton05();
}
public static Singleton05 getInstance() {
return Mgr07Holder.INSTANCE;
}
public void m() {
System.out.println("m");
}
}