保证在内存中只有一个实例存在
1.饿汉式
/**
* 饿汉式
* 类加载到内存后,就实例化一个单例,JVM保证线程安全
* 简单实用,推荐使用!
* 缺点:不管用到与否,类装载时就完成实例化
*/
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {};
public static Singleton getInstance() {
return INSTANCE;
}
}
2.懒汉式,线程不安全(一)
/**
* 懒汉式
* 虽然达到了按需初始化的目的,但多线程访问时会有问题
* 如果多线程访问,当一个线程调用getInstance方法时,判断INSTANCE 为空,但是这个线程还没new一个实例出来,另一个线程也调用了getInstance方法,此时INSTANCE同样为空,第二个线程也会继续new一个Singleton实例,此时两个实例不是同一个实例。
*/
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
//调用getInstance时判断INSTANCE是否为空,为空才初始化
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
3.懒汉式,线程安全(二)
/**
* 懒汉式
* 可以通过synchronized解决,但也带来效率下降
*/
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
4.懒汉式(三)
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {
}
public static Singleton getInstance() {
if (INSTANCE == null) {
//妄图通过减小同步代码块的方式提高效率,然后不可行
synchronized (Singleton.class) {
INSTANCE = new Singleton();
}
}
return INSTANCE;
}
}
5.懒汉式,双重校验锁(四)
public class Singleton {
private static volatile Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) {
//双重检查
synchronized (Singleton.class) {
if(INSTANCE == null) {
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}
6.静态内部类方式
/**
* 静态内部类方式
* JVM保证单例
* 加载外部类时不会加载内部类,这样可以实现懒加载
* 完美单例
*/
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private final static Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
7.枚举单例
/**
* 不仅可以解决线程同步,还可以防止反序列化。
* 完美中的完美。
*/
public enum Singleton {
INSTANCE;
public static void main(String[] args) {
Singleton.INSTANCE;
}
}