Java单例模式

本文最后更新于:2022年7月6日 下午

概览:单例模式、volatile

单例模式

类只需要有一个对象,不希望有更多的对象。

可以避免反复初始化和释放,这样会占用很多的资源,使用单例模式常驻内存可以节约资源。

单例模式与静态类的选择

  • 不需要维护任何状态、仅全局访问,适用于静态类。
  • 需要维持一些特定的状态,此时更适合使用单例模式。

饿汉式

1
2
3
4
5
6
7
8
9
10
11
public class Singleton {

private static Singleton INSTANCE = new Singleton();

private Singleton(){
}

public static Singleton getInstance(){
return INSTANCE;
}
}
  • 静态代码在被加载后就进行了初始化
  • 天然的线程安全
  • 但是没有起到延迟加载的效果。

懒汉式 - 线程安全

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Singleton {

private volatile static Singleton INSTANCE;

private Singleton(){
}

public static Singleton getInstance(){
if(INSTANCE == null){
synchronized (Singleton.class){
if(INSTANCE == null){
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
  • Double Ckeck Lock:防止获取到锁之后,覆盖已经被初始化的实例
  • synchronized:加锁,保证只有一个线程能获取到锁
  • volatile:保证可见性与有序性,防止指令重排。

静态类内部加载

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Singleton {

private Singleton(){
}

private static class LazyHolder{
private static final Singleton INSTANCE = new Singleton();
}

public Singleton getInstance(){
return LazyHolder.INSTANCE;
}
}
  • 静态内部类不会在单例类加载的时候就加载,而是在调用getInstance()方法是被加载
  • 线程安全的。

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