饿汉式
/**
* 饿汉式--单例模式
* 线程安全: static只在类加载时实例化一次
*/
public class SingleTon1 {
private static final SingleTon1 singleTon = new SingleTon1();
private SingleTon1() {
}
public static SingleTon1 getInstance() {
return singleTon;
}
}
懒汉式1
/**
* 懒汉式式--单例模式
* dcl单例
*/
public class SingleTon2 {
private static volatile SingleTon2 singleTon;
private SingleTon2() {
}
public static SingleTon2 getInstance() {
if (singleTon == null) {
synchronized (SingleTon2.class) {
if (singleTon == null) {
return new SingleTon2();
}
}
}
return singleTon;
}
}
懒汉式2(饿汉式升级)
/**
* 懒汉式--单例模式
* 线程安全:加载SingleTon3不会实例化单例(静态内部类)
*/
public class SingleTon3 {
private SingleTon3() {
}
private static class SingleTon3Holder {
private static final SingleTon3 singleTon = new SingleTon3();
}
public static SingleTon3 getInstance() {
return SingleTon3Holder.singleTon;
}
}
懒汉式3(最佳实践)
/**
* 懒汉式--单例模式
* 枚举天生单例,防止反序列化
*/
public enum SingleTon5Enum {
INSTANCE;
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
}
总结:
1.前三种写法,在反射调用时无法保证单例。可以在构造器非空判断抛异常来防止重复构造。
2.前三种写法,如果想实现序列化,除了 implements Serializable,还需要加入:
private Object readResolve(){
return singleTon;
}
3.空间与时间:饿汉式--空间换时间,懒汉式--时间换空间
4.单元素的枚举类型:天然单例,满足序列化,经常成为Singleton的最佳实践。