引用:https://www.cnblogs.com/ttylinux/p/6498822.html?utm_source=itdadao&utm_medium=referral
一 饿汉式
二 懒汉式
1. 双检锁
public class DoubleCheckedLockingSingleton {
// java中使用双重检查锁定机制,由于Java编译器和JIT的优化的原因系统无法保证我们期望的执行次序。
// 在java5.0修改了内存模型,使用volatile声明的变量可以强制屏蔽编译器和JIT的优化工作
private volatile static DoubleCheckedLockingSingleton uniqueInstance;
private DoubleCheckedLockingSingleton() {
}
public static DoubleCheckedLockingSingleton getInstance() {
if (uniqueInstance == null) {
synchronized (DoubleCheckedLockingSingleton.class) {
if (uniqueInstance == null) {
uniqueInstance = new DoubleCheckedLockingSingleton();
}
}
}
return uniqueInstance;
}
}
2. 静态内部类
public class LazyInitHolderSingleton {
private LazyInitHolderSingleton() {
}
private static class SingletonHolder {
private static final LazyInitHolderSingleton INSTANCE = new LazyInitHolderSingleton();
}
public static LazyInitHolderSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
根据jvm规范,当某对象第一次调用LazyInitHolderSingleton.getInstance()时,LazyInitHolderSingleton类被首次主动使用,jvm对其进行初始化(此时并不会调用LazyInitHolderSingleton()构造方法;进行LazyInitHolderSingleton的类加载,初始化静态变量),然后LazyInitHolderSingleton调用getInstance()方法,该方法中,又首次主动使用了SingletonHolder类,所以要对SingletonHolder类进行初始化(类的静态变量首先加载,进行初始化),初始化中,INSTANCE常量被赋值时才调用了 LazyInitHolderSingleton的构造方法LazyInitHolderSingleton(),完成了实例化并返回该实例。
3. 使用枚举类的方式来实现单例
public enum SingletonClass {
INSTANCE;
private String name;
public void test() {
System.out.println("The Test!");
}
public void setName(String name){
this.name= name;
}
public String getName(){
return name;
}
}
public class TestMain {
public static void main(String[] args) {
SingletonClass one = SingletonClass.INSTANCE;
SingletonClass two = SingletonClass.INSTANCE;
one.test();
one.setName("I am a SingletonClass Instance");
System.out.println(one.getName());
if (one == two) {
System.out.println("There are same");
}
}
}
4. 反射
在被序列化的类中添加readResolve方法,避免反射破坏单例模式。